From 66acfa6882152de9f7b5181e708de02bb97d42a8 Mon Sep 17 00:00:00 2001 From: Alexander Strizhakov Date: Mon, 27 Apr 2020 10:28:05 +0300 Subject: [PATCH 01/10] descriptions that module names are shortened --- config/description.exs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/config/description.exs b/config/description.exs index 7fac1e561..62e4cda7a 100644 --- a/config/description.exs +++ b/config/description.exs @@ -28,7 +28,8 @@ config :pleroma, :config_description, [ %{ key: :filters, type: {:list, :module}, - description: "List of filter modules for uploads", + description: + "List of filter modules for uploads. Module names are shortened (removed leading `Pleroma.Upload.Filter.` part), but on adding custom MRF module you need to use full name.", suggestions: Generator.list_modules_in_dir( "lib/pleroma/upload/filter", @@ -681,7 +682,8 @@ config :pleroma, :config_description, [ %{ key: :federation_publisher_modules, type: {:list, :module}, - description: "List of modules for federation publishing", + description: + "List of modules for federation publishing. Module names are shortened (removed leading `Pleroma.Web.` part), but on adding custom MRF module you need to use full name.", suggestions: [ Pleroma.Web.ActivityPub.Publisher ] @@ -694,7 +696,8 @@ config :pleroma, :config_description, [ %{ key: :rewrite_policy, type: [:module, {:list, :module}], - description: "A list of MRF policies enabled", + description: + "A list of enabled MRF policies. Module names are shortened (removed leading `Pleroma.Web.ActivityPub.MRF.` part), but on adding custom MRF module you need to use full name.", suggestions: Generator.list_modules_in_dir( "lib/pleroma/web/activity_pub/mrf", @@ -1975,7 +1978,8 @@ config :pleroma, :config_description, [ %{ key: :parsers, type: {:list, :module}, - description: "List of Rich Media parsers.", + description: + "List of Rich Media parsers. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parsers.` part), but on adding custom MRF module you need to use full name.", suggestions: [ Pleroma.Web.RichMedia.Parsers.MetaTagsParser, Pleroma.Web.RichMedia.Parsers.OEmbed, @@ -1987,7 +1991,8 @@ config :pleroma, :config_description, [ key: :ttl_setters, label: "TTL setters", type: {:list, :module}, - description: "List of rich media TTL setters.", + description: + "List of rich media TTL setters. Module names are shortened (removed leading `Pleroma.Web.RichMedia.Parser.` part), but on adding custom MRF module you need to use full name.", suggestions: [ Pleroma.Web.RichMedia.Parser.TTL.AwsSignedUrl ] @@ -2674,6 +2679,8 @@ config :pleroma, :config_description, [ %{ key: :scrub_policy, type: {:list, :module}, + description: + "Module names are shortened (removed leading `Pleroma.HTML.` part), but on adding custom MRF module you need to use full name.", suggestions: [Pleroma.HTML.Transform.MediaProxy, Pleroma.HTML.Scrubber.Default] } ] From f57fa2a00df2d93eba53c1ff3ab5c7d5fabb8308 Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 7 May 2020 12:43:30 +0200 Subject: [PATCH 02/10] Notifications: Simplify recipient calculation for some Activities. Fixes the 'getting notfications for other people's posts' bug. --- lib/pleroma/notification.ex | 29 ++++++++++++++++++++++------- test/notification_test.exs | 24 ++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 98289af08..b14e7c843 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -339,13 +339,7 @@ defmodule Pleroma.Notification do def get_notified_from_activity(%Activity{data: %{"type" => type}} = activity, local_only) when type in ["Create", "Like", "Announce", "Follow", "Move", "EmojiReact"] do - potential_receiver_ap_ids = - [] - |> Utils.maybe_notify_to_recipients(activity) - |> Utils.maybe_notify_mentioned_recipients(activity) - |> Utils.maybe_notify_subscribers(activity) - |> Utils.maybe_notify_followers(activity) - |> Enum.uniq() + potential_receiver_ap_ids = get_potential_receiver_ap_ids(activity) potential_receivers = User.get_users_from_set(potential_receiver_ap_ids, local_only) @@ -363,6 +357,27 @@ defmodule Pleroma.Notification do def get_notified_from_activity(_, _local_only), do: {[], []} + # For some actitivies, only notifity the author of the object + def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}}) + when type in ~w{Like Announce EmojiReact} do + case Object.get_cached_by_ap_id(object_id) do + %Object{data: %{"actor" => actor}} -> + [actor] + + _ -> + [] + end + end + + def get_potential_receiver_ap_ids(activity) do + [] + |> Utils.maybe_notify_to_recipients(activity) + |> Utils.maybe_notify_mentioned_recipients(activity) + |> Utils.maybe_notify_subscribers(activity) + |> Utils.maybe_notify_followers(activity) + |> Enum.uniq() + end + @doc "Filters out AP IDs domain-blocking and not following the activity's actor" def exclude_domain_blocker_ap_ids(ap_ids, activity, preloaded_users \\ []) diff --git a/test/notification_test.exs b/test/notification_test.exs index 5c85f3368..509ca0b0b 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -12,6 +12,8 @@ defmodule Pleroma.NotificationTest do alias Pleroma.Notification alias Pleroma.Tests.ObanHelpers alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.ActivityPub.Builder alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI alias Pleroma.Web.MastodonAPI.NotificationView @@ -601,6 +603,28 @@ defmodule Pleroma.NotificationTest do assert other_user not in enabled_receivers end + test "it only notifies the post's author in likes" do + user = insert(:user) + other_user = insert(:user) + third_user = insert(:user) + + {:ok, activity_one} = + CommonAPI.post(user, %{ + "status" => "hey @#{other_user.nickname}!" + }) + + {:ok, like_data, _} = Builder.like(third_user, activity_one.object) + + {:ok, like, _} = + like_data + |> Map.put("to", [other_user.ap_id | like_data["to"]]) + |> ActivityPub.persist(local: true) + + {enabled_receivers, _disabled_receivers} = Notification.get_notified_from_activity(like) + + assert other_user not in enabled_receivers + end + test "it does not send notification to mentioned users in announces" do user = insert(:user) other_user = insert(:user) From 8ae4d64d475405f8ff98868b80fc71fbe74b45bc Mon Sep 17 00:00:00 2001 From: lain Date: Thu, 7 May 2020 11:01:52 +0000 Subject: [PATCH 03/10] Apply suggestion to lib/pleroma/notification.ex --- lib/pleroma/notification.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index b14e7c843..af49fd713 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -357,7 +357,7 @@ defmodule Pleroma.Notification do def get_notified_from_activity(_, _local_only), do: {[], []} - # For some actitivies, only notifity the author of the object + # For some activities, only notify the author of the object def get_potential_receiver_ap_ids(%{data: %{"type" => type, "object" => object_id}}) when type in ~w{Like Announce EmojiReact} do case Object.get_cached_by_ap_id(object_id) do From 0e1bda55e856cd97b82ed393b719653872c93e34 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Fri, 8 May 2020 21:33:56 +0300 Subject: [PATCH 04/10] PleromaFE bundle dropping requirement for embedded account relationships in statuses / notifications. https://git.pleroma.social/pleroma/pleroma-fe/-/commit/7a0e554daf843fe9e98053e79ec0114c380ededb --- priv/static/index.html | 2 +- .../static/font/fontello.1588419330867.woff | Bin 13836 -> 0 bytes .../static/font/fontello.1588419330867.woff2 | Bin 11712 -> 0 bytes ...9330867.eot => fontello.1588947937982.eot} | Bin 22752 -> 22976 bytes ...9330867.svg => fontello.1588947937982.svg} | 2 ++ ...9330867.ttf => fontello.1588947937982.ttf} | Bin 22584 -> 22808 bytes .../static/font/fontello.1588947937982.woff | Bin 0 -> 13988 bytes .../static/font/fontello.1588947937982.woff2 | Bin 0 -> 11816 bytes ...9330867.css => fontello.1588947937982.css} | 14 ++++++++------ priv/static/static/fontello.json | 6 ++++++ ...9fca99e19.js => 2.18e4adec273c4ce867a8.js} | 4 ++-- ...9.js.map => 2.18e4adec273c4ce867a8.js.map} | 2 +- .../static/js/app.996428ccaaaa7f28cb8d.js | 2 ++ .../static/js/app.996428ccaaaa7f28cb8d.js.map | 1 + .../static/js/app.fa89b90e606f4facd209.js | 2 -- .../static/js/app.fa89b90e606f4facd209.js.map | 1 - ...js => vendors~app.561a1c605d1dfb0e6f74.js} | 16 ++++++++-------- .../vendors~app.561a1c605d1dfb0e6f74.js.map | 1 + .../vendors~app.8aa781e6dd81307f544b.js.map | 1 - priv/static/sw-pleroma.js | 2 +- 20 files changed, 33 insertions(+), 23 deletions(-) delete mode 100644 priv/static/static/font/fontello.1588419330867.woff delete mode 100644 priv/static/static/font/fontello.1588419330867.woff2 rename priv/static/static/font/{fontello.1588419330867.eot => fontello.1588947937982.eot} (90%) rename priv/static/static/font/{fontello.1588419330867.svg => fontello.1588947937982.svg} (98%) rename priv/static/static/font/{fontello.1588419330867.ttf => fontello.1588947937982.ttf} (90%) create mode 100644 priv/static/static/font/fontello.1588947937982.woff create mode 100644 priv/static/static/font/fontello.1588947937982.woff2 rename priv/static/static/{fontello.1588419330867.css => fontello.1588947937982.css} (88%) rename priv/static/static/js/{2.1c407059cd79fca99e19.js => 2.18e4adec273c4ce867a8.js} (80%) rename priv/static/static/js/{2.1c407059cd79fca99e19.js.map => 2.18e4adec273c4ce867a8.js.map} (98%) create mode 100644 priv/static/static/js/app.996428ccaaaa7f28cb8d.js create mode 100644 priv/static/static/js/app.996428ccaaaa7f28cb8d.js.map delete mode 100644 priv/static/static/js/app.fa89b90e606f4facd209.js delete mode 100644 priv/static/static/js/app.fa89b90e606f4facd209.js.map rename priv/static/static/js/{vendors~app.8aa781e6dd81307f544b.js => vendors~app.561a1c605d1dfb0e6f74.js} (87%) create mode 100644 priv/static/static/js/vendors~app.561a1c605d1dfb0e6f74.js.map delete mode 100644 priv/static/static/js/vendors~app.8aa781e6dd81307f544b.js.map diff --git a/priv/static/index.html b/priv/static/index.html index 4fac5c100..b37cbaa67 100644 --- a/priv/static/index.html +++ b/priv/static/index.html @@ -1 +1 @@ -Pleroma
\ No newline at end of file +Pleroma
\ No newline at end of file diff --git a/priv/static/static/font/fontello.1588419330867.woff b/priv/static/static/font/fontello.1588419330867.woff deleted file mode 100644 index 2bf4cbc16bfaf89c8e663c3ecdfdea1728fe781d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13836 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 adN{Y<|J>^Vp>Qot4UGdp^rZL;0Q?_|L~vFB diff --git a/priv/static/static/font/fontello.1588419330867.woff2 b/priv/static/static/font/fontello.1588419330867.woff2 deleted file mode 100644 index a31bf3f29df33e61b0472ae87e44d05efe32d05a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11712 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 delta 477 zcmX@Gneo9!Mz#kL3=9?#6WPpIisc>LCOUN2S1~X!1~4!%geB)D7WCBLUkBu`U|?YR zm0VV$!1n*&7X}6&1)#h_T0wel*Te~tK)wS519w4sVsQabTmZQbuxrzYg%`$)j>?c`(Y*!y3UnL{Aq~dH}*#DbA0gypYa`KZC z_e?!y%)sCl0_2zECRP+M_VF$Q@=pNy3VDgSsb}Yk0}XV0!N9iqgb62WF&A&1&&u~GcbHIfnWv;28PWE?48z|mpZ>^l5um8FOKK8`O3h}4D=8K z!>!9)TVeF%4Q}R)mXlw&-JN{Wy@Inx-W=?B%gufs+{{3UDDR@p=e##FZf^Ir + + diff --git a/priv/static/static/font/fontello.1588419330867.ttf b/priv/static/static/font/fontello.1588947937982.ttf similarity index 90% rename from priv/static/static/font/fontello.1588419330867.ttf rename to priv/static/static/font/fontello.1588947937982.ttf index 7dc4f108b7be4e5c132da254f00e70a6463d8102..443801c4fc0b48e45cf0ae16472319b6b95eb52a 100644 GIT binary patch delta 720 zcmZuuT}V@57=FI*?3|gKHPm#%m}~ybv_L8p#R4;6Gz@kY!ah4eSWnkypksCldSHVNb>+^oqwFlZDyx-3rC2FdepdFh zM$N2^Xk*%h7S@V+&X4PhT4~2st>!iEa4?!x{#F{b%KoqN%RD1`X#+{sIAUT=V-VPJ9W=b^6Y0kA3caPeE?f|r(1nT7vGyh|3Z3KT1rcIOV&F)DGoAutQ3k7}&D>~eFo-&Iu`a#X+{c_P&62&_YEhbf0vMFe{TBc89*DS>NjB&w{diC(edgVZb*f%TvCA0+a7Wc|71JMlQ3)Z^z>S zy)oQRq(5xb2W6hfB^c4eWJ2v7-{F=wZvTr*M^62QK`7UrzqM_N{=@v>q=yaVmC4U+ sE+6z=Yp`2?wBMz)_JKp{2cJQpcq@?RY*?KRs!S3yawr{9t5aU%9~x-Cj{pDw delta 495 zcmbQSiE+mU#tF*xRSXP_0SpWbVad6P1wHlm*8%w}7#LW7C6|>bu>Jq{g@M6G0VuDK zR*;_CHE}{Dknh02z+I4@SX=-U7Xb1lfHX&XPGy?Ok43Hw3~Wmn80_*gQWH}ojUs_^ zt|CBrvkagB`$-lc+tmliSINjNsW{sg_WveO0A$dUoc!d(JyTB^GcdS?0Qn`ki4_Hm zeZ0$n{1ZUFLSABS>e;#CKm*-gFfcHkEyyn}S$Y1K76XIl4j@0SpeVKAsiXED28Qqr z6MsZA&Ym2?nC|YyzzEdL!05uj3})#7X)d60F9sGykh|3w6c|_-*j}i-P=8_c!sJ8$ zhm#*3e0cid^M`*Qg+5ArwEO7z(dA>xWELjP$@)xMs*FG#c~Dru0D?uBaB>qLF^Yeh*z_bBG0)fS59+qw<@uv(7AAy*`oPpt!2?R4(FfeT1!PaTL`LEM^ zCK)#e`Qmtfo39Mq%s?+QFxxcR=1B@Y0vQ;sA6 diff --git a/priv/static/static/font/fontello.1588947937982.woff b/priv/static/static/font/fontello.1588947937982.woff new file mode 100644 index 0000000000000000000000000000000000000000..e96fea75766b8087fd2e064329a1e21500d2e522 GIT binary patch literal 13988 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 X|4Xk6sLZuE1q3D#oGa-A5YYbt*N?ji literal 0 HcmV?d00001 diff --git a/priv/static/static/font/fontello.1588947937982.woff2 b/priv/static/static/font/fontello.1588947937982.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..50318a6703694b2888e6be5f00b39e91435e3105 GIT binary patch literal 11816 zcmV+@F4xg_Pew8T0RR9104^v14*&oF09hCS04>k}0RR9100000000000000000000 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 Wp?_x}4h)=p4)p!;5VXmQ10De4ugL!Z literal 0 HcmV?d00001 diff --git a/priv/static/static/fontello.1588419330867.css b/priv/static/static/fontello.1588947937982.css similarity index 88% rename from priv/static/static/fontello.1588419330867.css rename to priv/static/static/fontello.1588947937982.css index 198eff184..d3d77a8b5 100644 --- a/priv/static/static/fontello.1588419330867.css +++ b/priv/static/static/fontello.1588947937982.css @@ -1,11 +1,11 @@ @font-face { font-family: "Icons"; - src: url("./font/fontello.1588419330867.eot"); - src: url("./font/fontello.1588419330867.eot") format("embedded-opentype"), - url("./font/fontello.1588419330867.woff2") format("woff2"), - url("./font/fontello.1588419330867.woff") format("woff"), - url("./font/fontello.1588419330867.ttf") format("truetype"), - url("./font/fontello.1588419330867.svg") format("svg"); + src: url("./font/fontello.1588947937982.eot"); + src: url("./font/fontello.1588947937982.eot") format("embedded-opentype"), + url("./font/fontello.1588947937982.woff2") format("woff2"), + url("./font/fontello.1588947937982.woff") format("woff"), + url("./font/fontello.1588947937982.ttf") format("truetype"), + url("./font/fontello.1588947937982.svg") format("svg"); font-weight: normal; font-style: normal; } @@ -137,6 +137,8 @@ .icon-link::before { content: "\e823"; } +.icon-share::before { content: "\f1e0"; } + .icon-user::before { content: "\e824"; } .icon-ok::before { content: "\e827"; } diff --git a/priv/static/static/fontello.json b/priv/static/static/fontello.json index 5963b68b4..7f0e7cdd5 100755 --- a/priv/static/static/fontello.json +++ b/priv/static/static/fontello.json @@ -346,6 +346,12 @@ "code": 59427, "src": "fontawesome" }, + { + "uid": "4aad6bb50b02c18508aae9cbe14e784e", + "css": "share", + "code": 61920, + "src": "fontawesome" + }, { "uid": "8b80d36d4ef43889db10bc1f0dc9a862", "css": "user", diff --git a/priv/static/static/js/2.1c407059cd79fca99e19.js b/priv/static/static/js/2.18e4adec273c4ce867a8.js similarity index 80% rename from priv/static/static/js/2.1c407059cd79fca99e19.js rename to priv/static/static/js/2.18e4adec273c4ce867a8.js index 14018d92a..d191aa852 100644 --- a/priv/static/static/js/2.1c407059cd79fca99e19.js +++ b/priv/static/static/js/2.18e4adec273c4ce867a8.js @@ -1,2 +1,2 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{585:function(t,e,i){var c=i(586);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(4).default)("2eec4758",c,!0,{})},586:function(t,e,i){(t.exports=i(3)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--accent,#d8a070))}",""])},587:function(t,e,i){"use strict";i.r(e);var c=i(91),n={components:{TabSwitcher:i(53).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,n=this.$store;fetch(t).then((function(t){t.blob().then((function(t){var a=new File([t],e,{mimetype:"image/png"}),r=new FormData;r.append("file",a),c.a.uploadMedia({store:n,formData:r}).then((function(t){i.$emit("uploaded",t),i.clear()}),(function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")}))}))}))}}},a=i(0);var r=function(t){i(585)},s=Object(a.a)(n,(function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,(function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,(function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){return i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])})),0)})),0)],1)}),[],!1,r,null,null);e.default=s.exports}}]); -//# sourceMappingURL=2.1c407059cd79fca99e19.js.map \ No newline at end of file +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{587:function(t,e,i){var c=i(588);"string"==typeof c&&(c=[[t.i,c,""]]),c.locals&&(t.exports=c.locals);(0,i(3).default)("2eec4758",c,!0,{})},588:function(t,e,i){(t.exports=i(2)(!1)).push([t.i,".sticker-picker{width:100%}.sticker-picker .contents{min-height:250px}.sticker-picker .contents .sticker-picker-content{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;padding:0 4px}.sticker-picker .contents .sticker-picker-content .sticker{display:-ms-flexbox;display:flex;-ms-flex:1 1 auto;flex:1 1 auto;margin:4px;width:56px;height:56px}.sticker-picker .contents .sticker-picker-content .sticker img{height:100%}.sticker-picker .contents .sticker-picker-content .sticker img:hover{filter:drop-shadow(0 0 5px var(--accent,#d8a070))}",""])},589:function(t,e,i){"use strict";i.r(e);var c=i(91),n={components:{TabSwitcher:i(53).a},data:function(){return{meta:{stickers:[]},path:""}},computed:{pack:function(){return this.$store.state.instance.stickers||[]}},methods:{clear:function(){this.meta={stickers:[]}},pick:function(t,e){var i=this,n=this.$store;fetch(t).then((function(t){t.blob().then((function(t){var a=new File([t],e,{mimetype:"image/png"}),r=new FormData;r.append("file",a),c.a.uploadMedia({store:n,formData:r}).then((function(t){i.$emit("uploaded",t),i.clear()}),(function(t){console.warn("Can't attach sticker"),console.warn(t),i.$emit("upload-failed","default")}))}))}))}}},a=i(0);var r=function(t){i(587)},s=Object(a.a)(n,(function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"sticker-picker"},[i("tab-switcher",{staticClass:"tab-switcher",attrs:{"render-only-focused":!0,"scrollable-tabs":""}},t._l(t.pack,(function(e){return i("div",{key:e.path,staticClass:"sticker-picker-content",attrs:{"image-tooltip":e.meta.title,image:e.path+e.meta.tabIcon}},t._l(e.meta.stickers,(function(c){return i("div",{key:c,staticClass:"sticker",on:{click:function(i){return i.stopPropagation(),i.preventDefault(),t.pick(e.path+c,e.meta.title)}}},[i("img",{attrs:{src:e.path+c}})])})),0)})),0)],1)}),[],!1,r,null,null);e.default=s.exports}}]); +//# sourceMappingURL=2.18e4adec273c4ce867a8.js.map \ No newline at end of file diff --git a/priv/static/static/js/2.1c407059cd79fca99e19.js.map b/priv/static/static/js/2.18e4adec273c4ce867a8.js.map similarity index 98% rename from priv/static/static/js/2.1c407059cd79fca99e19.js.map rename to priv/static/static/js/2.18e4adec273c4ce867a8.js.map index cfee79ea8..a7f98bfef 100644 --- a/priv/static/static/js/2.1c407059cd79fca99e19.js.map +++ b/priv/static/static/js/2.18e4adec273c4ce867a8.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack:///./src/components/sticker_picker/sticker_picker.vue?e513","webpack:///./src/components/sticker_picker/sticker_picker.vue?1909","webpack:///./src/components/sticker_picker/sticker_picker.js","webpack:///./src/components/sticker_picker/sticker_picker.vue","webpack:///./src/components/sticker_picker/sticker_picker.vue?7504"],"names":["content","module","i","locals","exports","add","default","push","StickerPicker","components","TabSwitcher","data","meta","stickers","path","computed","pack","this","$store","state","instance","methods","clear","pick","sticker","name","store","fetch","then","res","blob","file","File","mimetype","formData","FormData","append","statusPosterService","uploadMedia","fileData","$emit","error","console","warn","__vue_styles__","context","Component","_vm","_h","$createElement","_c","_self","staticClass","attrs","_l","stickerpack","key","title","tabIcon","on","$event","stopPropagation","preventDefault"],"mappings":"6EAGA,IAAIA,EAAU,EAAQ,KACA,iBAAZA,IAAsBA,EAAU,CAAC,CAACC,EAAOC,EAAIF,EAAS,MAC7DA,EAAQG,SAAQF,EAAOG,QAAUJ,EAAQG,SAG/BE,EADH,EAAQ,GAAkEC,SACnE,WAAYN,GAAS,EAAM,K,qBCRlCC,EAAOG,QAAU,EAAQ,EAAR,EAA4D,IAK/EG,KAAK,CAACN,EAAOC,EAAI,4iBAA6iB,M,oDC8CvjBM,EA/CO,CACpBC,WAAY,CACVC,Y,MAAAA,GAEFC,KAJoB,WAKlB,MAAO,CACLC,KAAM,CACJC,SAAU,IAEZC,KAAM,KAGVC,SAAU,CACRC,KADQ,WAEN,OAAOC,KAAKC,OAAOC,MAAMC,SAASP,UAAY,KAGlDQ,QAAS,CACPC,MADO,WAELL,KAAKL,KAAO,CACVC,SAAU,KAGdU,KANO,SAMDC,EAASC,GAAM,WACbC,EAAQT,KAAKC,OAEnBS,MAAMH,GACHI,MAAK,SAACC,GACLA,EAAIC,OAAOF,MAAK,SAACE,GACf,IAAIC,EAAO,IAAIC,KAAK,CAACF,GAAOL,EAAM,CAAEQ,SAAU,cAC1CC,EAAW,IAAIC,SACnBD,EAASE,OAAO,OAAQL,GACxBM,IAAoBC,YAAY,CAAEZ,QAAOQ,aACtCN,MAAK,SAACW,GACL,EAAKC,MAAM,WAAYD,GACvB,EAAKjB,WACJ,SAACmB,GACFC,QAAQC,KAAK,wBACbD,QAAQC,KAAKF,GACb,EAAKD,MAAM,gBAAiB,uB,OCnC5C,IAEII,EAVJ,SAAsBC,GACpB,EAAQ,MAeNC,EAAY,YACd,GCjBW,WAAa,IAAIC,EAAI9B,KAAS+B,EAAGD,EAAIE,eAAmBC,EAAGH,EAAII,MAAMD,IAAIF,EAAG,OAAOE,EAAG,MAAM,CAACE,YAAY,kBAAkB,CAACF,EAAG,eAAe,CAACE,YAAY,eAAeC,MAAM,CAAC,uBAAsB,EAAK,kBAAkB,KAAKN,EAAIO,GAAIP,EAAQ,MAAE,SAASQ,GAAa,OAAOL,EAAG,MAAM,CAACM,IAAID,EAAYzC,KAAKsC,YAAY,yBAAyBC,MAAM,CAAC,gBAAgBE,EAAY3C,KAAK6C,MAAM,MAAQF,EAAYzC,KAAOyC,EAAY3C,KAAK8C,UAAUX,EAAIO,GAAIC,EAAY3C,KAAa,UAAE,SAASY,GAAS,OAAO0B,EAAG,MAAM,CAACM,IAAIhC,EAAQ4B,YAAY,UAAUO,GAAG,CAAC,MAAQ,SAASC,GAAyD,OAAjDA,EAAOC,kBAAkBD,EAAOE,iBAAwBf,EAAIxB,KAAKgC,EAAYzC,KAAOU,EAAS+B,EAAY3C,KAAK6C,UAAU,CAACP,EAAG,MAAM,CAACG,MAAM,CAAC,IAAME,EAAYzC,KAAOU,UAAe,MAAK,IAAI,KACjvB,IDOY,EAahCoB,EAToB,KAEU,MAYjB,UAAAE,EAAiB","file":"static/js/2.1c407059cd79fca99e19.js","sourcesContent":["// style-loader: Adds some css to the DOM by adding a \n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./checkbox.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./checkbox.vue\"\nimport __vue_script__ from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./checkbox.vue\"\n/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-01a5cae8\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./checkbox.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('label',{staticClass:\"checkbox\",class:{ disabled: _vm.disabled, indeterminate: _vm.indeterminate }},[_c('input',{attrs:{\"type\":\"checkbox\",\"disabled\":_vm.disabled},domProps:{\"checked\":_vm.checked,\"indeterminate\":_vm.indeterminate},on:{\"change\":function($event){return _vm.$emit('change', $event.target.checked)}}}),_vm._v(\" \"),_c('i',{staticClass:\"checkbox-indicator\"}),_vm._v(\" \"),(!!_vm.$slots.default)?_c('span',{staticClass:\"label\"},[_vm._t(\"default\")],2):_vm._e()])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import { filter, sortBy, includes } from 'lodash'\n\nexport const notificationsFromStore = store => store.state.statuses.notifications.data\n\nexport const visibleTypes = store => ([\n store.state.config.notificationVisibility.likes && 'like',\n store.state.config.notificationVisibility.mentions && 'mention',\n store.state.config.notificationVisibility.repeats && 'repeat',\n store.state.config.notificationVisibility.follows && 'follow',\n store.state.config.notificationVisibility.followRequest && 'follow_request',\n store.state.config.notificationVisibility.moves && 'move',\n store.state.config.notificationVisibility.emojiReactions && 'pleroma:emoji_reaction'\n].filter(_ => _))\n\nconst statusNotifications = ['like', 'mention', 'repeat', 'pleroma:emoji_reaction']\n\nexport const isStatusNotification = (type) => includes(statusNotifications, type)\n\nconst sortById = (a, b) => {\n const seqA = Number(a.id)\n const seqB = Number(b.id)\n const isSeqA = !Number.isNaN(seqA)\n const isSeqB = !Number.isNaN(seqB)\n if (isSeqA && isSeqB) {\n return seqA > seqB ? -1 : 1\n } else if (isSeqA && !isSeqB) {\n return 1\n } else if (!isSeqA && isSeqB) {\n return -1\n } else {\n return a.id > b.id ? -1 : 1\n }\n}\n\nexport const filteredNotificationsFromStore = (store, types) => {\n // map is just to clone the array since sort mutates it and it causes some issues\n let sortedNotifications = notificationsFromStore(store).map(_ => _).sort(sortById)\n sortedNotifications = sortBy(sortedNotifications, 'seen')\n return sortedNotifications.filter(\n (notification) => (types || visibleTypes(store)).includes(notification.type)\n )\n}\n\nexport const unseenNotificationsFromStore = store =>\n filter(filteredNotificationsFromStore(store), ({ seen }) => !seen)\n","import { includes } from 'lodash'\n\nconst generateProfileLink = (id, screenName, restrictedNicknames) => {\n const complicated = !screenName || (isExternal(screenName) || includes(restrictedNicknames, screenName))\n return {\n name: (complicated ? 'external-user-profile' : 'user-profile'),\n params: (complicated ? { id } : { name: screenName })\n }\n}\n\nconst isExternal = screenName => screenName && screenName.includes('@')\n\nexport default generateProfileLink\n","// TODO this func might as well take the entire file and use its mimetype\n// or the entire service could be just mimetype service that only operates\n// on mimetypes and not files. Currently the naming is confusing.\nconst fileType = mimetype => {\n if (mimetype.match(/text\\/html/)) {\n return 'html'\n }\n\n if (mimetype.match(/image/)) {\n return 'image'\n }\n\n if (mimetype.match(/video/)) {\n return 'video'\n }\n\n if (mimetype.match(/audio/)) {\n return 'audio'\n }\n\n return 'unknown'\n}\n\nconst fileMatchesSomeType = (types, file) =>\n types.some(type => fileType(file.mimetype) === type)\n\nconst fileTypeService = {\n fileType,\n fileMatchesSomeType\n}\n\nexport default fileTypeService\n","const DialogModal = {\n props: {\n darkOverlay: {\n default: true,\n type: Boolean\n },\n onCancel: {\n default: () => {},\n type: Function\n }\n }\n}\n\nexport default DialogModal\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./dialog_modal.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./dialog_modal.js\"\nimport __vue_script__ from \"!!babel-loader!./dialog_modal.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-70b9d662\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./dialog_modal.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('span',{class:{ 'dark-overlay': _vm.darkOverlay },on:{\"click\":function($event){if($event.target !== $event.currentTarget){ return null; }$event.stopPropagation();return _vm.onCancel()}}},[_c('div',{staticClass:\"dialog-modal panel panel-default\",on:{\"click\":function($event){$event.stopPropagation();}}},[_c('div',{staticClass:\"panel-heading dialog-modal-heading\"},[_c('div',{staticClass:\"title\"},[_vm._t(\"header\")],2)]),_vm._v(\" \"),_c('div',{staticClass:\"dialog-modal-content\"},[_vm._t(\"default\")],2),_vm._v(\" \"),_c('div',{staticClass:\"dialog-modal-footer user-interactions panel-footer\"},[_vm._t(\"footer\")],2)])])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import DialogModal from '../dialog_modal/dialog_modal.vue'\nimport Popover from '../popover/popover.vue'\n\nconst FORCE_NSFW = 'mrf_tag:media-force-nsfw'\nconst STRIP_MEDIA = 'mrf_tag:media-strip'\nconst FORCE_UNLISTED = 'mrf_tag:force-unlisted'\nconst DISABLE_REMOTE_SUBSCRIPTION = 'mrf_tag:disable-remote-subscription'\nconst DISABLE_ANY_SUBSCRIPTION = 'mrf_tag:disable-any-subscription'\nconst SANDBOX = 'mrf_tag:sandbox'\nconst QUARANTINE = 'mrf_tag:quarantine'\n\nconst ModerationTools = {\n props: [\n 'user'\n ],\n data () {\n return {\n tags: {\n FORCE_NSFW,\n STRIP_MEDIA,\n FORCE_UNLISTED,\n DISABLE_REMOTE_SUBSCRIPTION,\n DISABLE_ANY_SUBSCRIPTION,\n SANDBOX,\n QUARANTINE\n },\n showDeleteUserDialog: false,\n toggled: false\n }\n },\n components: {\n DialogModal,\n Popover\n },\n computed: {\n tagsSet () {\n return new Set(this.user.tags)\n },\n hasTagPolicy () {\n return this.$store.state.instance.tagPolicyAvailable\n }\n },\n methods: {\n hasTag (tagName) {\n return this.tagsSet.has(tagName)\n },\n toggleTag (tag) {\n const store = this.$store\n if (this.tagsSet.has(tag)) {\n store.state.api.backendInteractor.untagUser({ user: this.user, tag }).then(response => {\n if (!response.ok) { return }\n store.commit('untagUser', { user: this.user, tag })\n })\n } else {\n store.state.api.backendInteractor.tagUser({ user: this.user, tag }).then(response => {\n if (!response.ok) { return }\n store.commit('tagUser', { user: this.user, tag })\n })\n }\n },\n toggleRight (right) {\n const store = this.$store\n if (this.user.rights[right]) {\n store.state.api.backendInteractor.deleteRight({ user: this.user, right }).then(response => {\n if (!response.ok) { return }\n store.commit('updateRight', { user: this.user, right, value: false })\n })\n } else {\n store.state.api.backendInteractor.addRight({ user: this.user, right }).then(response => {\n if (!response.ok) { return }\n store.commit('updateRight', { user: this.user, right, value: true })\n })\n }\n },\n toggleActivationStatus () {\n this.$store.dispatch('toggleActivationStatus', { user: this.user })\n },\n deleteUserDialog (show) {\n this.showDeleteUserDialog = show\n },\n deleteUser () {\n const store = this.$store\n const user = this.user\n const { id, name } = user\n store.state.api.backendInteractor.deleteUser({ user })\n .then(e => {\n this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)\n const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile'\n const isTargetUser = this.$route.params.name === name || this.$route.params.id === id\n if (isProfile && isTargetUser) {\n window.history.back()\n }\n })\n },\n setToggled (value) {\n this.toggled = value\n }\n }\n}\n\nexport default ModerationTools\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./moderation_tools.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./moderation_tools.js\"\nimport __vue_script__ from \"!!babel-loader!./moderation_tools.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-168f1ca6\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./moderation_tools.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('Popover',{staticClass:\"moderation-tools-popover\",attrs:{\"trigger\":\"click\",\"placement\":\"bottom\",\"offset\":{ y: 5 }},on:{\"show\":function($event){return _vm.setToggled(true)},\"close\":function($event){return _vm.setToggled(false)}}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_c('div',{staticClass:\"dropdown-menu\"},[(_vm.user.is_local)?_c('span',[_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleRight(\"admin\")}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t(!!_vm.user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin'))+\"\\n \")]),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleRight(\"moderator\")}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t(!!_vm.user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator'))+\"\\n \")]),_vm._v(\" \"),_c('div',{staticClass:\"dropdown-divider\",attrs:{\"role\":\"separator\"}})]):_vm._e(),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleActivationStatus()}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t(!!_vm.user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account'))+\"\\n \")]),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.deleteUserDialog(true)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.delete_account'))+\"\\n \")]),_vm._v(\" \"),(_vm.hasTagPolicy)?_c('div',{staticClass:\"dropdown-divider\",attrs:{\"role\":\"separator\"}}):_vm._e(),_vm._v(\" \"),(_vm.hasTagPolicy)?_c('span',[_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.FORCE_NSFW)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.force_nsfw'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.FORCE_NSFW) }})]),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.STRIP_MEDIA)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.strip_media'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.STRIP_MEDIA) }})]),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.FORCE_UNLISTED)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.force_unlisted'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.FORCE_UNLISTED) }})]),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.SANDBOX)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.sandbox'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.SANDBOX) }})]),_vm._v(\" \"),(_vm.user.is_local)?_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.DISABLE_REMOTE_SUBSCRIPTION)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.disable_remote_subscription'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.DISABLE_REMOTE_SUBSCRIPTION) }})]):_vm._e(),_vm._v(\" \"),(_vm.user.is_local)?_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.DISABLE_ANY_SUBSCRIPTION)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.disable_any_subscription'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.DISABLE_ANY_SUBSCRIPTION) }})]):_vm._e(),_vm._v(\" \"),(_vm.user.is_local)?_c('button',{staticClass:\"dropdown-item\",on:{\"click\":function($event){return _vm.toggleTag(_vm.tags.QUARANTINE)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.quarantine'))+\"\\n \"),_c('span',{staticClass:\"menu-checkbox\",class:{ 'menu-checkbox-checked': _vm.hasTag(_vm.tags.QUARANTINE) }})]):_vm._e()]):_vm._e()])]),_vm._v(\" \"),_c('button',{staticClass:\"btn btn-default btn-block\",class:{ toggled: _vm.toggled },attrs:{\"slot\":\"trigger\"},slot:\"trigger\"},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.moderation'))+\"\\n \")])]),_vm._v(\" \"),_c('portal',{attrs:{\"to\":\"modal\"}},[(_vm.showDeleteUserDialog)?_c('DialogModal',{attrs:{\"on-cancel\":_vm.deleteUserDialog.bind(this, false)}},[_c('template',{slot:\"header\"},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.delete_user'))+\"\\n \")]),_vm._v(\" \"),_c('p',[_vm._v(_vm._s(_vm.$t('user_card.admin_menu.delete_user_confirmation')))]),_vm._v(\" \"),_c('template',{slot:\"footer\"},[_c('button',{staticClass:\"btn btn-default\",on:{\"click\":function($event){return _vm.deleteUserDialog(false)}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('general.cancel'))+\"\\n \")]),_vm._v(\" \"),_c('button',{staticClass:\"btn btn-default danger\",on:{\"click\":function($event){return _vm.deleteUser()}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.admin_menu.delete_user'))+\"\\n \")])])],2):_vm._e()],1)],1)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import ProgressButton from '../progress_button/progress_button.vue'\nimport Popover from '../popover/popover.vue'\n\nconst AccountActions = {\n props: [\n 'user', 'relationship'\n ],\n data () {\n return { }\n },\n components: {\n ProgressButton,\n Popover\n },\n methods: {\n showRepeats () {\n this.$store.dispatch('showReblogs', this.user.id)\n },\n hideRepeats () {\n this.$store.dispatch('hideReblogs', this.user.id)\n },\n blockUser () {\n this.$store.dispatch('blockUser', this.user.id)\n },\n unblockUser () {\n this.$store.dispatch('unblockUser', this.user.id)\n },\n reportUser () {\n this.$store.dispatch('openUserReportingModal', this.user.id)\n }\n }\n}\n\nexport default AccountActions\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./account_actions.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./account_actions.js\"\nimport __vue_script__ from \"!!babel-loader!./account_actions.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-bf5e6e30\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./account_actions.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"account-actions\"},[_c('Popover',{attrs:{\"trigger\":\"click\",\"placement\":\"bottom\"}},[_c('div',{staticClass:\"account-tools-popover\",attrs:{\"slot\":\"content\"},slot:\"content\"},[_c('div',{staticClass:\"dropdown-menu\"},[(_vm.relationship.following)?[(_vm.relationship.showing_reblogs)?_c('button',{staticClass:\"btn btn-default dropdown-item\",on:{\"click\":_vm.hideRepeats}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.hide_repeats'))+\"\\n \")]):_vm._e(),_vm._v(\" \"),(!_vm.relationship.showing_reblogs)?_c('button',{staticClass:\"btn btn-default dropdown-item\",on:{\"click\":_vm.showRepeats}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.show_repeats'))+\"\\n \")]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"dropdown-divider\",attrs:{\"role\":\"separator\"}})]:_vm._e(),_vm._v(\" \"),(_vm.relationship.blocking)?_c('button',{staticClass:\"btn btn-default btn-block dropdown-item\",on:{\"click\":_vm.unblockUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.unblock'))+\"\\n \")]):_c('button',{staticClass:\"btn btn-default btn-block dropdown-item\",on:{\"click\":_vm.blockUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.block'))+\"\\n \")]),_vm._v(\" \"),_c('button',{staticClass:\"btn btn-default btn-block dropdown-item\",on:{\"click\":_vm.reportUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.report'))+\"\\n \")])],2)]),_vm._v(\" \"),_c('div',{staticClass:\"btn btn-default ellipsis-button\",attrs:{\"slot\":\"trigger\"},slot:\"trigger\"},[_c('i',{staticClass:\"icon-ellipsis trigger-button\"})])])],1)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import UserAvatar from '../user_avatar/user_avatar.vue'\nimport RemoteFollow from '../remote_follow/remote_follow.vue'\nimport ProgressButton from '../progress_button/progress_button.vue'\nimport FollowButton from '../follow_button/follow_button.vue'\nimport ModerationTools from '../moderation_tools/moderation_tools.vue'\nimport AccountActions from '../account_actions/account_actions.vue'\nimport generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'\nimport { mapGetters } from 'vuex'\n\nexport default {\n props: [\n 'userId', 'switcher', 'selected', 'hideBio', 'rounded', 'bordered', 'allowZoomingAvatar'\n ],\n data () {\n return {\n followRequestInProgress: false,\n betterShadow: this.$store.state.interface.browserSupport.cssFilter\n }\n },\n created () {\n this.$store.dispatch('fetchUserRelationship', this.user.id)\n },\n computed: {\n user () {\n return this.$store.getters.findUser(this.userId)\n },\n relationship () {\n return this.$store.getters.relationship(this.userId)\n },\n classes () {\n return [{\n 'user-card-rounded-t': this.rounded === 'top', // set border-top-left-radius and border-top-right-radius\n 'user-card-rounded': this.rounded === true, // set border-radius for all sides\n 'user-card-bordered': this.bordered === true // set border for all sides\n }]\n },\n style () {\n return {\n backgroundImage: [\n `linear-gradient(to bottom, var(--profileTint), var(--profileTint))`,\n `url(${this.user.cover_photo})`\n ].join(', ')\n }\n },\n isOtherUser () {\n return this.user.id !== this.$store.state.users.currentUser.id\n },\n subscribeUrl () {\n // eslint-disable-next-line no-undef\n const serverUrl = new URL(this.user.statusnet_profile_url)\n return `${serverUrl.protocol}//${serverUrl.host}/main/ostatus`\n },\n loggedIn () {\n return this.$store.state.users.currentUser\n },\n dailyAvg () {\n const days = Math.ceil((new Date() - new Date(this.user.created_at)) / (60 * 60 * 24 * 1000))\n return Math.round(this.user.statuses_count / days)\n },\n userHighlightType: {\n get () {\n const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]\n return (data && data.type) || 'disabled'\n },\n set (type) {\n const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]\n if (type !== 'disabled') {\n this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: (data && data.color) || '#FFFFFF', type })\n } else {\n this.$store.dispatch('setHighlight', { user: this.user.screen_name, color: undefined })\n }\n },\n ...mapGetters(['mergedConfig'])\n },\n userHighlightColor: {\n get () {\n const data = this.$store.getters.mergedConfig.highlight[this.user.screen_name]\n return data && data.color\n },\n set (color) {\n this.$store.dispatch('setHighlight', { user: this.user.screen_name, color })\n }\n },\n visibleRole () {\n const rights = this.user.rights\n if (!rights) { return }\n const validRole = rights.admin || rights.moderator\n const roleTitle = rights.admin ? 'admin' : 'moderator'\n return validRole && roleTitle\n },\n hideFollowsCount () {\n return this.isOtherUser && this.user.hide_follows_count\n },\n hideFollowersCount () {\n return this.isOtherUser && this.user.hide_followers_count\n },\n ...mapGetters(['mergedConfig'])\n },\n components: {\n UserAvatar,\n RemoteFollow,\n ModerationTools,\n AccountActions,\n ProgressButton,\n FollowButton\n },\n methods: {\n muteUser () {\n this.$store.dispatch('muteUser', this.user.id)\n },\n unmuteUser () {\n this.$store.dispatch('unmuteUser', this.user.id)\n },\n subscribeUser () {\n return this.$store.dispatch('subscribeUser', this.user.id)\n },\n unsubscribeUser () {\n return this.$store.dispatch('unsubscribeUser', this.user.id)\n },\n setProfileView (v) {\n if (this.switcher) {\n const store = this.$store\n store.commit('setProfileView', { v })\n }\n },\n linkClicked ({ target }) {\n if (target.tagName === 'SPAN') {\n target = target.parentNode\n }\n if (target.tagName === 'A') {\n window.open(target.href, '_blank')\n }\n },\n userProfileLink (user) {\n return generateProfileLink(\n user.id, user.screen_name,\n this.$store.state.instance.restrictedNicknames\n )\n },\n zoomAvatar () {\n const attachment = {\n url: this.user.profile_image_url_original,\n mimetype: 'image'\n }\n this.$store.dispatch('setMedia', [attachment])\n this.$store.dispatch('setCurrent', attachment)\n },\n mentionUser () {\n this.$store.dispatch('openPostStatusModal', { replyTo: true, repliedUser: this.user })\n }\n }\n}\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./user_card.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./user_card.js\"\nimport __vue_script__ from \"!!babel-loader!./user_card.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-4d895630\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./user_card.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"user-card\",class:_vm.classes},[_c('div',{staticClass:\"background-image\",class:{ 'hide-bio': _vm.hideBio },style:(_vm.style)}),_vm._v(\" \"),_c('div',{staticClass:\"panel-heading\"},[_c('div',{staticClass:\"user-info\"},[_c('div',{staticClass:\"container\"},[(_vm.allowZoomingAvatar)?_c('a',{staticClass:\"user-info-avatar-link\",on:{\"click\":_vm.zoomAvatar}},[_c('UserAvatar',{attrs:{\"better-shadow\":_vm.betterShadow,\"user\":_vm.user}}),_vm._v(\" \"),_vm._m(0)],1):_c('router-link',{attrs:{\"to\":_vm.userProfileLink(_vm.user)}},[_c('UserAvatar',{attrs:{\"better-shadow\":_vm.betterShadow,\"user\":_vm.user}})],1),_vm._v(\" \"),_c('div',{staticClass:\"user-summary\"},[_c('div',{staticClass:\"top-line\"},[(_vm.user.name_html)?_c('div',{staticClass:\"user-name\",attrs:{\"title\":_vm.user.name},domProps:{\"innerHTML\":_vm._s(_vm.user.name_html)}}):_c('div',{staticClass:\"user-name\",attrs:{\"title\":_vm.user.name}},[_vm._v(\"\\n \"+_vm._s(_vm.user.name)+\"\\n \")]),_vm._v(\" \"),(!_vm.isOtherUser)?_c('router-link',{attrs:{\"to\":{ name: 'user-settings' }}},[_c('i',{staticClass:\"button-icon icon-wrench usersettings\",attrs:{\"title\":_vm.$t('tool_tip.user_settings')}})]):_vm._e(),_vm._v(\" \"),(_vm.isOtherUser && !_vm.user.is_local)?_c('a',{attrs:{\"href\":_vm.user.statusnet_profile_url,\"target\":\"_blank\"}},[_c('i',{staticClass:\"icon-link-ext usersettings\"})]):_vm._e(),_vm._v(\" \"),(_vm.isOtherUser && _vm.loggedIn)?_c('AccountActions',{attrs:{\"user\":_vm.user,\"relationship\":_vm.relationship}}):_vm._e()],1),_vm._v(\" \"),_c('div',{staticClass:\"bottom-line\"},[_c('router-link',{staticClass:\"user-screen-name\",attrs:{\"to\":_vm.userProfileLink(_vm.user)}},[_vm._v(\"\\n @\"+_vm._s(_vm.user.screen_name)+\"\\n \")]),_vm._v(\" \"),(!_vm.hideBio && !!_vm.visibleRole)?_c('span',{staticClass:\"alert staff\"},[_vm._v(_vm._s(_vm.visibleRole))]):_vm._e(),_vm._v(\" \"),(_vm.user.locked)?_c('span',[_c('i',{staticClass:\"icon icon-lock\"})]):_vm._e(),_vm._v(\" \"),(!_vm.mergedConfig.hideUserStats && !_vm.hideBio)?_c('span',{staticClass:\"dailyAvg\"},[_vm._v(_vm._s(_vm.dailyAvg)+\" \"+_vm._s(_vm.$t('user_card.per_day')))]):_vm._e()],1)])],1),_vm._v(\" \"),_c('div',{staticClass:\"user-meta\"},[(_vm.relationship.followed_by && _vm.loggedIn && _vm.isOtherUser)?_c('div',{staticClass:\"following\"},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.follows_you'))+\"\\n \")]):_vm._e(),_vm._v(\" \"),(_vm.isOtherUser && (_vm.loggedIn || !_vm.switcher))?_c('div',{staticClass:\"highlighter\"},[(_vm.userHighlightType !== 'disabled')?_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.userHighlightColor),expression:\"userHighlightColor\"}],staticClass:\"userHighlightText\",attrs:{\"id\":'userHighlightColorTx'+_vm.user.id,\"type\":\"text\"},domProps:{\"value\":(_vm.userHighlightColor)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.userHighlightColor=$event.target.value}}}):_vm._e(),_vm._v(\" \"),(_vm.userHighlightType !== 'disabled')?_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.userHighlightColor),expression:\"userHighlightColor\"}],staticClass:\"userHighlightCl\",attrs:{\"id\":'userHighlightColor'+_vm.user.id,\"type\":\"color\"},domProps:{\"value\":(_vm.userHighlightColor)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.userHighlightColor=$event.target.value}}}):_vm._e(),_vm._v(\" \"),_c('label',{staticClass:\"userHighlightSel select\",attrs:{\"for\":\"style-switcher\"}},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.userHighlightType),expression:\"userHighlightType\"}],staticClass:\"userHighlightSel\",attrs:{\"id\":'userHighlightSel'+_vm.user.id},on:{\"change\":function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.userHighlightType=$event.target.multiple ? $$selectedVal : $$selectedVal[0]}}},[_c('option',{attrs:{\"value\":\"disabled\"}},[_vm._v(\"No highlight\")]),_vm._v(\" \"),_c('option',{attrs:{\"value\":\"solid\"}},[_vm._v(\"Solid bg\")]),_vm._v(\" \"),_c('option',{attrs:{\"value\":\"striped\"}},[_vm._v(\"Striped bg\")]),_vm._v(\" \"),_c('option',{attrs:{\"value\":\"side\"}},[_vm._v(\"Side stripe\")])]),_vm._v(\" \"),_c('i',{staticClass:\"icon-down-open\"})])]):_vm._e()]),_vm._v(\" \"),(_vm.loggedIn && _vm.isOtherUser)?_c('div',{staticClass:\"user-interactions\"},[_c('div',{staticClass:\"btn-group\"},[_c('FollowButton',{attrs:{\"relationship\":_vm.relationship}}),_vm._v(\" \"),(_vm.relationship.following)?[(!_vm.relationship.subscribing)?_c('ProgressButton',{staticClass:\"btn btn-default\",attrs:{\"click\":_vm.subscribeUser,\"title\":_vm.$t('user_card.subscribe')}},[_c('i',{staticClass:\"icon-bell-alt\"})]):_c('ProgressButton',{staticClass:\"btn btn-default toggled\",attrs:{\"click\":_vm.unsubscribeUser,\"title\":_vm.$t('user_card.unsubscribe')}},[_c('i',{staticClass:\"icon-bell-ringing-o\"})])]:_vm._e()],2),_vm._v(\" \"),_c('div',[(_vm.relationship.muting)?_c('button',{staticClass:\"btn btn-default btn-block toggled\",on:{\"click\":_vm.unmuteUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.muted'))+\"\\n \")]):_c('button',{staticClass:\"btn btn-default btn-block\",on:{\"click\":_vm.muteUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.mute'))+\"\\n \")])]),_vm._v(\" \"),_c('div',[_c('button',{staticClass:\"btn btn-default btn-block\",on:{\"click\":_vm.mentionUser}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('user_card.mention'))+\"\\n \")])]),_vm._v(\" \"),(_vm.loggedIn.role === \"admin\")?_c('ModerationTools',{attrs:{\"user\":_vm.user}}):_vm._e()],1):_vm._e(),_vm._v(\" \"),(!_vm.loggedIn && _vm.user.is_local)?_c('div',{staticClass:\"user-interactions\"},[_c('RemoteFollow',{attrs:{\"user\":_vm.user}})],1):_vm._e()])]),_vm._v(\" \"),(!_vm.hideBio)?_c('div',{staticClass:\"panel-body\"},[(!_vm.mergedConfig.hideUserStats && _vm.switcher)?_c('div',{staticClass:\"user-counts\"},[_c('div',{staticClass:\"user-count\",on:{\"click\":function($event){$event.preventDefault();return _vm.setProfileView('statuses')}}},[_c('h5',[_vm._v(_vm._s(_vm.$t('user_card.statuses')))]),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(_vm.user.statuses_count)+\" \"),_c('br')])]),_vm._v(\" \"),_c('div',{staticClass:\"user-count\",on:{\"click\":function($event){$event.preventDefault();return _vm.setProfileView('friends')}}},[_c('h5',[_vm._v(_vm._s(_vm.$t('user_card.followees')))]),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(_vm.hideFollowsCount ? _vm.$t('user_card.hidden') : _vm.user.friends_count))])]),_vm._v(\" \"),_c('div',{staticClass:\"user-count\",on:{\"click\":function($event){$event.preventDefault();return _vm.setProfileView('followers')}}},[_c('h5',[_vm._v(_vm._s(_vm.$t('user_card.followers')))]),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(_vm.hideFollowersCount ? _vm.$t('user_card.hidden') : _vm.user.followers_count))])])]):_vm._e(),_vm._v(\" \"),(!_vm.hideBio && _vm.user.description_html)?_c('p',{staticClass:\"user-card-bio\",domProps:{\"innerHTML\":_vm._s(_vm.user.description_html)},on:{\"click\":function($event){$event.preventDefault();return _vm.linkClicked($event)}}}):(!_vm.hideBio)?_c('p',{staticClass:\"user-card-bio\"},[_vm._v(\"\\n \"+_vm._s(_vm.user.description)+\"\\n \")]):_vm._e()]):_vm._e()])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"user-info-avatar-link-overlay\"},[_c('i',{staticClass:\"button-icon icon-zoom-in\"})])}]\nexport { render, staticRenderFns }","import StillImage from '../still-image/still-image.vue'\n\nconst UserAvatar = {\n props: [\n 'user',\n 'betterShadow',\n 'compact'\n ],\n data () {\n return {\n showPlaceholder: false\n }\n },\n components: {\n StillImage\n },\n computed: {\n imgSrc () {\n return this.showPlaceholder ? '/images/avi.png' : this.user.profile_image_url_original\n }\n },\n methods: {\n imageLoadError () {\n this.showPlaceholder = true\n }\n },\n watch: {\n src () {\n this.showPlaceholder = false\n }\n }\n}\n\nexport default UserAvatar\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./user_avatar.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./user_avatar.js\"\nimport __vue_script__ from \"!!babel-loader!./user_avatar.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-056a5e34\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./user_avatar.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('StillImage',{staticClass:\"avatar\",class:{ 'avatar-compact': _vm.compact, 'better-shadow': _vm.betterShadow },attrs:{\"alt\":_vm.user.screen_name,\"title\":_vm.user.screen_name,\"src\":_vm.imgSrc,\"image-load-error\":_vm.imageLoadError}})}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import { mapGetters } from 'vuex'\n\nconst FavoriteButton = {\n props: ['status', 'loggedIn'],\n data () {\n return {\n animated: false\n }\n },\n methods: {\n favorite () {\n if (!this.status.favorited) {\n this.$store.dispatch('favorite', { id: this.status.id })\n } else {\n this.$store.dispatch('unfavorite', { id: this.status.id })\n }\n this.animated = true\n setTimeout(() => {\n this.animated = false\n }, 500)\n }\n },\n computed: {\n classes () {\n return {\n 'icon-star-empty': !this.status.favorited,\n 'icon-star': this.status.favorited,\n 'animate-spin': this.animated\n }\n },\n ...mapGetters(['mergedConfig'])\n }\n}\n\nexport default FavoriteButton\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./favorite_button.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./favorite_button.js\"\nimport __vue_script__ from \"!!babel-loader!./favorite_button.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-2ced002f\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./favorite_button.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.loggedIn)?_c('div',[_c('i',{staticClass:\"button-icon favorite-button fav-active\",class:_vm.classes,attrs:{\"title\":_vm.$t('tool_tip.favorite')},on:{\"click\":function($event){$event.preventDefault();return _vm.favorite()}}}),_vm._v(\" \"),(!_vm.mergedConfig.hidePostStats && _vm.status.fave_num > 0)?_c('span',[_vm._v(_vm._s(_vm.status.fave_num))]):_vm._e()]):_c('div',[_c('i',{staticClass:\"button-icon favorite-button\",class:_vm.classes,attrs:{\"title\":_vm.$t('tool_tip.favorite')}}),_vm._v(\" \"),(!_vm.mergedConfig.hidePostStats && _vm.status.fave_num > 0)?_c('span',[_vm._v(_vm._s(_vm.status.fave_num))]):_vm._e()])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Popover from '../popover/popover.vue'\nimport { mapGetters } from 'vuex'\n\nconst ReactButton = {\n props: ['status'],\n data () {\n return {\n filterWord: ''\n }\n },\n components: {\n Popover\n },\n methods: {\n addReaction (event, emoji, close) {\n const existingReaction = this.status.emoji_reactions.find(r => r.name === emoji)\n if (existingReaction && existingReaction.me) {\n this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })\n } else {\n this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })\n }\n close()\n }\n },\n computed: {\n commonEmojis () {\n return ['❤️', '😠', '👀', '😂', '🔥']\n },\n emojis () {\n if (this.filterWord !== '') {\n return this.$store.state.instance.emoji.filter(emoji => emoji.displayText.includes(this.filterWord))\n }\n return this.$store.state.instance.emoji || []\n },\n ...mapGetters(['mergedConfig'])\n }\n}\n\nexport default ReactButton\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./react_button.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./react_button.js\"\nimport __vue_script__ from \"!!babel-loader!./react_button.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-185f65eb\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./react_button.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Popover',{staticClass:\"react-button-popover\",attrs:{\"trigger\":\"click\",\"placement\":\"top\",\"offset\":{ y: 5 }},scopedSlots:_vm._u([{key:\"content\",fn:function(ref){\nvar close = ref.close;\nreturn _c('div',{},[_c('div',{staticClass:\"reaction-picker-filter\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.filterWord),expression:\"filterWord\"}],attrs:{\"placeholder\":_vm.$t('emoji.search_emoji')},domProps:{\"value\":(_vm.filterWord)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.filterWord=$event.target.value}}})]),_vm._v(\" \"),_c('div',{staticClass:\"reaction-picker\"},[_vm._l((_vm.commonEmojis),function(emoji){return _c('span',{key:emoji,staticClass:\"emoji-button\",on:{\"click\":function($event){return _vm.addReaction($event, emoji, close)}}},[_vm._v(\"\\n \"+_vm._s(emoji)+\"\\n \")])}),_vm._v(\" \"),_c('div',{staticClass:\"reaction-picker-divider\"}),_vm._v(\" \"),_vm._l((_vm.emojis),function(emoji,key){return _c('span',{key:key,staticClass:\"emoji-button\",on:{\"click\":function($event){return _vm.addReaction($event, emoji.replacement, close)}}},[_vm._v(\"\\n \"+_vm._s(emoji.replacement)+\"\\n \")])}),_vm._v(\" \"),_c('div',{staticClass:\"reaction-bottom-fader\"})],2)])}}])},[_vm._v(\" \"),_c('i',{staticClass:\"icon-smile button-icon add-reaction-button\",attrs:{\"slot\":\"trigger\",\"title\":_vm.$t('tool_tip.add_reaction')},slot:\"trigger\"})])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import { mapGetters } from 'vuex'\n\nconst RetweetButton = {\n props: ['status', 'loggedIn', 'visibility'],\n data () {\n return {\n animated: false\n }\n },\n methods: {\n retweet () {\n if (!this.status.repeated) {\n this.$store.dispatch('retweet', { id: this.status.id })\n } else {\n this.$store.dispatch('unretweet', { id: this.status.id })\n }\n this.animated = true\n setTimeout(() => {\n this.animated = false\n }, 500)\n }\n },\n computed: {\n classes () {\n return {\n 'retweeted': this.status.repeated,\n 'retweeted-empty': !this.status.repeated,\n 'animate-spin': this.animated\n }\n },\n ...mapGetters(['mergedConfig'])\n }\n}\n\nexport default RetweetButton\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./retweet_button.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./retweet_button.js\"\nimport __vue_script__ from \"!!babel-loader!./retweet_button.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-538410cc\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./retweet_button.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.loggedIn)?_c('div',[(_vm.visibility !== 'private' && _vm.visibility !== 'direct')?[_c('i',{staticClass:\"button-icon retweet-button icon-retweet rt-active\",class:_vm.classes,attrs:{\"title\":_vm.$t('tool_tip.repeat')},on:{\"click\":function($event){$event.preventDefault();return _vm.retweet()}}}),_vm._v(\" \"),(!_vm.mergedConfig.hidePostStats && _vm.status.repeat_num > 0)?_c('span',[_vm._v(_vm._s(_vm.status.repeat_num))]):_vm._e()]:[_c('i',{staticClass:\"button-icon icon-lock\",class:_vm.classes,attrs:{\"title\":_vm.$t('timeline.no_retweet_hint')}})]],2):(!_vm.loggedIn)?_c('div',[_c('i',{staticClass:\"button-icon icon-retweet\",class:_vm.classes,attrs:{\"title\":_vm.$t('tool_tip.repeat')}}),_vm._v(\" \"),(!_vm.mergedConfig.hidePostStats && _vm.status.repeat_num > 0)?_c('span',[_vm._v(_vm._s(_vm.status.repeat_num))]):_vm._e()]):_vm._e()}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Popover from '../popover/popover.vue'\n\nconst ExtraButtons = {\n props: [ 'status' ],\n components: { Popover },\n methods: {\n deleteStatus () {\n const confirmed = window.confirm(this.$t('status.delete_confirm'))\n if (confirmed) {\n this.$store.dispatch('deleteStatus', { id: this.status.id })\n }\n },\n pinStatus () {\n this.$store.dispatch('pinStatus', this.status.id)\n .then(() => this.$emit('onSuccess'))\n .catch(err => this.$emit('onError', err.error.error))\n },\n unpinStatus () {\n this.$store.dispatch('unpinStatus', this.status.id)\n .then(() => this.$emit('onSuccess'))\n .catch(err => this.$emit('onError', err.error.error))\n },\n muteConversation () {\n this.$store.dispatch('muteConversation', this.status.id)\n .then(() => this.$emit('onSuccess'))\n .catch(err => this.$emit('onError', err.error.error))\n },\n unmuteConversation () {\n this.$store.dispatch('unmuteConversation', this.status.id)\n .then(() => this.$emit('onSuccess'))\n .catch(err => this.$emit('onError', err.error.error))\n },\n copyLink () {\n navigator.clipboard.writeText(this.statusLink)\n .then(() => this.$emit('onSuccess'))\n .catch(err => this.$emit('onError', err.error.error))\n }\n },\n computed: {\n currentUser () { return this.$store.state.users.currentUser },\n canDelete () {\n if (!this.currentUser) { return }\n const superuser = this.currentUser.rights.moderator || this.currentUser.rights.admin\n return superuser || this.status.user.id === this.currentUser.id\n },\n ownStatus () {\n return this.status.user.id === this.currentUser.id\n },\n canPin () {\n return this.ownStatus && (this.status.visibility === 'public' || this.status.visibility === 'unlisted')\n },\n canMute () {\n return !!this.currentUser\n },\n statusLink () {\n return `${this.$store.state.instance.server}${this.$router.resolve({ name: 'conversation', params: { id: this.status.id } }).href}`\n }\n }\n}\n\nexport default ExtraButtons\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./extra_buttons.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./extra_buttons.js\"\nimport __vue_script__ from \"!!babel-loader!./extra_buttons.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-b30b8de6\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./extra_buttons.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Popover',{staticClass:\"extra-button-popover\",attrs:{\"trigger\":\"click\",\"placement\":\"top\"},scopedSlots:_vm._u([{key:\"content\",fn:function(ref){\nvar close = ref.close;\nreturn _c('div',{},[_c('div',{staticClass:\"dropdown-menu\"},[(_vm.canMute && !_vm.status.thread_muted)?_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":function($event){$event.preventDefault();return _vm.muteConversation($event)}}},[_c('i',{staticClass:\"icon-eye-off\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.mute_conversation\")))])]):_vm._e(),_vm._v(\" \"),(_vm.canMute && _vm.status.thread_muted)?_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":function($event){$event.preventDefault();return _vm.unmuteConversation($event)}}},[_c('i',{staticClass:\"icon-eye-off\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.unmute_conversation\")))])]):_vm._e(),_vm._v(\" \"),(!_vm.status.pinned && _vm.canPin)?_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":[function($event){$event.preventDefault();return _vm.pinStatus($event)},close]}},[_c('i',{staticClass:\"icon-pin\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.pin\")))])]):_vm._e(),_vm._v(\" \"),(_vm.status.pinned && _vm.canPin)?_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":[function($event){$event.preventDefault();return _vm.unpinStatus($event)},close]}},[_c('i',{staticClass:\"icon-pin\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.unpin\")))])]):_vm._e(),_vm._v(\" \"),(_vm.canDelete)?_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":[function($event){$event.preventDefault();return _vm.deleteStatus($event)},close]}},[_c('i',{staticClass:\"icon-cancel\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.delete\")))])]):_vm._e(),_vm._v(\" \"),_c('button',{staticClass:\"dropdown-item dropdown-item-icon\",on:{\"click\":[function($event){$event.preventDefault();return _vm.copyLink($event)},close]}},[_c('i',{staticClass:\"icon-share\"}),_c('span',[_vm._v(_vm._s(_vm.$t(\"status.copy_link\")))])])])])}}])},[_vm._v(\" \"),_c('i',{staticClass:\"icon-ellipsis button-icon\",attrs:{\"slot\":\"trigger\"},slot:\"trigger\"})])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import UserAvatar from '../user_avatar/user_avatar.vue'\nimport generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'\n\nconst AvatarList = {\n props: ['users'],\n computed: {\n slicedUsers () {\n return this.users ? this.users.slice(0, 15) : []\n }\n },\n components: {\n UserAvatar\n },\n methods: {\n userProfileLink (user) {\n return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)\n }\n }\n}\n\nexport default AvatarList\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./avatar_list.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./avatar_list.js\"\nimport __vue_script__ from \"!!babel-loader!./avatar_list.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-4cea5bcf\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./avatar_list.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"avatars\"},_vm._l((_vm.slicedUsers),function(user){return _c('router-link',{key:user.id,staticClass:\"avatars-item\",attrs:{\"to\":_vm.userProfileLink(user)}},[_c('UserAvatar',{staticClass:\"avatar-small\",attrs:{\"user\":user}})],1)}),1)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import StillImage from '../still-image/still-image.vue'\nimport VideoAttachment from '../video_attachment/video_attachment.vue'\nimport nsfwImage from '../../assets/nsfw.png'\nimport fileTypeService from '../../services/file_type/file_type.service.js'\nimport { mapGetters } from 'vuex'\n\nconst Attachment = {\n props: [\n 'attachment',\n 'nsfw',\n 'statusId',\n 'size',\n 'allowPlay',\n 'setMedia',\n 'naturalSizeLoad'\n ],\n data () {\n return {\n nsfwImage: this.$store.state.instance.nsfwCensorImage || nsfwImage,\n hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,\n preloadImage: this.$store.getters.mergedConfig.preloadImage,\n loading: false,\n img: fileTypeService.fileType(this.attachment.mimetype) === 'image' && document.createElement('img'),\n modalOpen: false,\n showHidden: false\n }\n },\n components: {\n StillImage,\n VideoAttachment\n },\n computed: {\n usePlaceHolder () {\n return this.size === 'hide' || this.type === 'unknown'\n },\n referrerpolicy () {\n return this.$store.state.instance.mediaProxyAvailable ? '' : 'no-referrer'\n },\n type () {\n return fileTypeService.fileType(this.attachment.mimetype)\n },\n hidden () {\n return this.nsfw && this.hideNsfwLocal && !this.showHidden\n },\n isEmpty () {\n return (this.type === 'html' && !this.attachment.oembed) || this.type === 'unknown'\n },\n isSmall () {\n return this.size === 'small'\n },\n fullwidth () {\n return this.type === 'html' || this.type === 'audio'\n },\n ...mapGetters(['mergedConfig'])\n },\n methods: {\n linkClicked ({ target }) {\n if (target.tagName === 'A') {\n window.open(target.href, '_blank')\n }\n },\n openModal (event) {\n const modalTypes = this.mergedConfig.playVideosInModal\n ? ['image', 'video']\n : ['image']\n if (fileTypeService.fileMatchesSomeType(modalTypes, this.attachment) ||\n this.usePlaceHolder\n ) {\n event.stopPropagation()\n event.preventDefault()\n this.setMedia()\n this.$store.dispatch('setCurrent', this.attachment)\n }\n },\n toggleHidden (event) {\n if (\n (this.mergedConfig.useOneClickNsfw && !this.showHidden) &&\n (this.type !== 'video' || this.mergedConfig.playVideosInModal)\n ) {\n this.openModal(event)\n return\n }\n if (this.img && !this.preloadImage) {\n if (this.img.onload) {\n this.img.onload()\n } else {\n this.loading = true\n this.img.src = this.attachment.url\n this.img.onload = () => {\n this.loading = false\n this.showHidden = !this.showHidden\n }\n }\n } else {\n this.showHidden = !this.showHidden\n }\n },\n onImageLoad (image) {\n const width = image.naturalWidth\n const height = image.naturalHeight\n this.naturalSizeLoad && this.naturalSizeLoad({ width, height })\n }\n }\n}\n\nexport default Attachment\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./attachment.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./attachment.js\"\nimport __vue_script__ from \"!!babel-loader!./attachment.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-61e0eb0c\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./attachment.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {\nvar _obj;\nvar _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.usePlaceHolder)?_c('div',{on:{\"click\":_vm.openModal}},[(_vm.type !== 'html')?_c('a',{staticClass:\"placeholder\",attrs:{\"target\":\"_blank\",\"href\":_vm.attachment.url}},[_vm._v(\"\\n [\"+_vm._s(_vm.nsfw ? \"NSFW/\" : \"\")+_vm._s(_vm.type.toUpperCase())+\"]\\n \")]):_vm._e()]):_c('div',{directives:[{name:\"show\",rawName:\"v-show\",value:(!_vm.isEmpty),expression:\"!isEmpty\"}],staticClass:\"attachment\",class:( _obj = {}, _obj[_vm.type] = true, _obj.loading = _vm.loading, _obj['fullwidth'] = _vm.fullwidth, _obj['nsfw-placeholder'] = _vm.hidden, _obj )},[(_vm.hidden)?_c('a',{staticClass:\"image-attachment\",attrs:{\"href\":_vm.attachment.url},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleHidden($event)}}},[_c('img',{key:_vm.nsfwImage,staticClass:\"nsfw\",class:{'small': _vm.isSmall},attrs:{\"src\":_vm.nsfwImage}}),_vm._v(\" \"),(_vm.type === 'video')?_c('i',{staticClass:\"play-icon icon-play-circled\"}):_vm._e()]):_vm._e(),_vm._v(\" \"),(_vm.nsfw && _vm.hideNsfwLocal && !_vm.hidden)?_c('div',{staticClass:\"hider\"},[_c('a',{attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleHidden($event)}}},[_vm._v(\"Hide\")])]):_vm._e(),_vm._v(\" \"),(_vm.type === 'image' && (!_vm.hidden || _vm.preloadImage))?_c('a',{staticClass:\"image-attachment\",class:{'hidden': _vm.hidden && _vm.preloadImage },attrs:{\"href\":_vm.attachment.url,\"target\":\"_blank\",\"title\":_vm.attachment.description},on:{\"click\":_vm.openModal}},[_c('StillImage',{attrs:{\"referrerpolicy\":_vm.referrerpolicy,\"mimetype\":_vm.attachment.mimetype,\"src\":_vm.attachment.large_thumb_url || _vm.attachment.url,\"image-load-handler\":_vm.onImageLoad}})],1):_vm._e(),_vm._v(\" \"),(_vm.type === 'video' && !_vm.hidden)?_c('a',{staticClass:\"video-container\",class:{'small': _vm.isSmall},attrs:{\"href\":_vm.allowPlay ? undefined : _vm.attachment.url},on:{\"click\":_vm.openModal}},[_c('VideoAttachment',{staticClass:\"video\",attrs:{\"attachment\":_vm.attachment,\"controls\":_vm.allowPlay}}),_vm._v(\" \"),(!_vm.allowPlay)?_c('i',{staticClass:\"play-icon icon-play-circled\"}):_vm._e()],1):_vm._e(),_vm._v(\" \"),(_vm.type === 'audio')?_c('audio',{attrs:{\"src\":_vm.attachment.url,\"controls\":\"\"}}):_vm._e(),_vm._v(\" \"),(_vm.type === 'html' && _vm.attachment.oembed)?_c('div',{staticClass:\"oembed\",on:{\"click\":function($event){$event.preventDefault();return _vm.linkClicked($event)}}},[(_vm.attachment.thumb_url)?_c('div',{staticClass:\"image\"},[_c('img',{attrs:{\"src\":_vm.attachment.thumb_url}})]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"text\"},[_c('h1',[_c('a',{attrs:{\"href\":_vm.attachment.url}},[_vm._v(_vm._s(_vm.attachment.oembed.title))])]),_vm._v(\" \"),_c('div',{domProps:{\"innerHTML\":_vm._s(_vm.attachment.oembed.oembedHTML)}})])]):_vm._e()])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Timeago from '../timeago/timeago.vue'\nimport { forEach, map } from 'lodash'\n\nexport default {\n name: 'Poll',\n props: ['basePoll'],\n components: { Timeago },\n data () {\n return {\n loading: false,\n choices: []\n }\n },\n created () {\n if (!this.$store.state.polls.pollsObject[this.pollId]) {\n this.$store.dispatch('mergeOrAddPoll', this.basePoll)\n }\n this.$store.dispatch('trackPoll', this.pollId)\n },\n destroyed () {\n this.$store.dispatch('untrackPoll', this.pollId)\n },\n computed: {\n pollId () {\n return this.basePoll.id\n },\n poll () {\n const storePoll = this.$store.state.polls.pollsObject[this.pollId]\n return storePoll || {}\n },\n options () {\n return (this.poll && this.poll.options) || []\n },\n expiresAt () {\n return (this.poll && this.poll.expires_at) || 0\n },\n expired () {\n return (this.poll && this.poll.expired) || false\n },\n loggedIn () {\n return this.$store.state.users.currentUser\n },\n showResults () {\n return this.poll.voted || this.expired || !this.loggedIn\n },\n totalVotesCount () {\n return this.poll.votes_count\n },\n containerClass () {\n return {\n loading: this.loading\n }\n },\n choiceIndices () {\n // Convert array of booleans into an array of indices of the\n // items that were 'true', so [true, false, false, true] becomes\n // [0, 3].\n return this.choices\n .map((entry, index) => entry && index)\n .filter(value => typeof value === 'number')\n },\n isDisabled () {\n const noChoice = this.choiceIndices.length === 0\n return this.loading || noChoice\n }\n },\n methods: {\n percentageForOption (count) {\n return this.totalVotesCount === 0 ? 0 : Math.round(count / this.totalVotesCount * 100)\n },\n resultTitle (option) {\n return `${option.votes_count}/${this.totalVotesCount} ${this.$t('polls.votes')}`\n },\n fetchPoll () {\n this.$store.dispatch('refreshPoll', { id: this.statusId, pollId: this.poll.id })\n },\n activateOption (index) {\n // forgive me father: doing checking the radio/checkboxes\n // in code because of customized input elements need either\n // a) an extra element for the actual graphic, or b) use a\n // pseudo element for the label. We use b) which mandates\n // using \"for\" and \"id\" matching which isn't nice when the\n // same poll appears multiple times on the site (notifs and\n // timeline for example). With code we can make sure it just\n // works without altering the pseudo element implementation.\n const allElements = this.$el.querySelectorAll('input')\n const clickedElement = this.$el.querySelector(`input[value=\"${index}\"]`)\n if (this.poll.multiple) {\n // Checkboxes, toggle only the clicked one\n clickedElement.checked = !clickedElement.checked\n } else {\n // Radio button, uncheck everything and check the clicked one\n forEach(allElements, element => { element.checked = false })\n clickedElement.checked = true\n }\n this.choices = map(allElements, e => e.checked)\n },\n optionId (index) {\n return `poll${this.poll.id}-${index}`\n },\n vote () {\n if (this.choiceIndices.length === 0) return\n this.loading = true\n this.$store.dispatch(\n 'votePoll',\n { id: this.statusId, pollId: this.poll.id, choices: this.choiceIndices }\n ).then(poll => {\n this.loading = false\n })\n }\n }\n}\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./poll.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./poll.js\"\nimport __vue_script__ from \"!!babel-loader!./poll.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-db51c57e\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./poll.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"poll\",class:_vm.containerClass},[_vm._l((_vm.options),function(option,index){return _c('div',{key:index,staticClass:\"poll-option\"},[(_vm.showResults)?_c('div',{staticClass:\"option-result\",attrs:{\"title\":_vm.resultTitle(option)}},[_c('div',{staticClass:\"option-result-label\"},[_c('span',{staticClass:\"result-percentage\"},[_vm._v(\"\\n \"+_vm._s(_vm.percentageForOption(option.votes_count))+\"%\\n \")]),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(option.title))])]),_vm._v(\" \"),_c('div',{staticClass:\"result-fill\",style:({ 'width': ((_vm.percentageForOption(option.votes_count)) + \"%\") })})]):_c('div',{on:{\"click\":function($event){return _vm.activateOption(index)}}},[(_vm.poll.multiple)?_c('input',{attrs:{\"type\":\"checkbox\",\"disabled\":_vm.loading},domProps:{\"value\":index}}):_c('input',{attrs:{\"type\":\"radio\",\"disabled\":_vm.loading},domProps:{\"value\":index}}),_vm._v(\" \"),_c('label',{staticClass:\"option-vote\"},[_c('div',[_vm._v(_vm._s(option.title))])])])])}),_vm._v(\" \"),_c('div',{staticClass:\"footer faint\"},[(!_vm.showResults)?_c('button',{staticClass:\"btn btn-default poll-vote-button\",attrs:{\"type\":\"button\",\"disabled\":_vm.isDisabled},on:{\"click\":_vm.vote}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('polls.vote'))+\"\\n \")]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"total\"},[_vm._v(\"\\n \"+_vm._s(_vm.totalVotesCount)+\" \"+_vm._s(_vm.$t(\"polls.votes\"))+\" · \\n \")]),_vm._v(\" \"),_c('i18n',{attrs:{\"path\":_vm.expired ? 'polls.expired' : 'polls.expires_in'}},[_c('Timeago',{attrs:{\"time\":_vm.expiresAt,\"auto-update\":60,\"now-threshold\":0}})],1)],1)],2)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Attachment from '../attachment/attachment.vue'\nimport { chunk, last, dropRight, sumBy } from 'lodash'\n\nconst Gallery = {\n props: [\n 'attachments',\n 'nsfw',\n 'setMedia'\n ],\n data () {\n return {\n sizes: {}\n }\n },\n components: { Attachment },\n computed: {\n rows () {\n if (!this.attachments) {\n return []\n }\n const rows = chunk(this.attachments, 3)\n if (last(rows).length === 1 && rows.length > 1) {\n // if 1 attachment on last row -> add it to the previous row instead\n const lastAttachment = last(rows)[0]\n const allButLastRow = dropRight(rows)\n last(allButLastRow).push(lastAttachment)\n return allButLastRow\n }\n return rows\n },\n useContainFit () {\n return this.$store.getters.mergedConfig.useContainFit\n }\n },\n methods: {\n onNaturalSizeLoad (id, size) {\n this.$set(this.sizes, id, size)\n },\n rowStyle (itemsPerRow) {\n return { 'padding-bottom': `${(100 / (itemsPerRow + 0.6))}%` }\n },\n itemStyle (id, row) {\n const total = sumBy(row, item => this.getAspectRatio(item.id))\n return { flex: `${this.getAspectRatio(id) / total} 1 0%` }\n },\n getAspectRatio (id) {\n const size = this.sizes[id]\n return size ? size.width / size.height : 1\n }\n }\n}\n\nexport default Gallery\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./gallery.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./gallery.js\"\nimport __vue_script__ from \"!!babel-loader!./gallery.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-68a574b8\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./gallery.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:\"galleryContainer\",staticStyle:{\"width\":\"100%\"}},_vm._l((_vm.rows),function(row,index){return _c('div',{key:index,staticClass:\"gallery-row\",class:{ 'contain-fit': _vm.useContainFit, 'cover-fit': !_vm.useContainFit },style:(_vm.rowStyle(row.length))},[_c('div',{staticClass:\"gallery-row-inner\"},_vm._l((row),function(attachment){return _c('attachment',{key:attachment.id,style:(_vm.itemStyle(attachment.id, row)),attrs:{\"set-media\":_vm.setMedia,\"nsfw\":_vm.nsfw,\"attachment\":attachment,\"allow-play\":false,\"natural-size-load\":_vm.onNaturalSizeLoad.bind(null, attachment.id)}})}),1)])}),0)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","const LinkPreview = {\n name: 'LinkPreview',\n props: [\n 'card',\n 'size',\n 'nsfw'\n ],\n data () {\n return {\n imageLoaded: false\n }\n },\n computed: {\n useImage () {\n // Currently BE shoudn't give cards if tagged NSFW, this is a bit paranoid\n // as it makes sure to hide the image if somehow NSFW tagged preview can\n // exist.\n return this.card.image && !this.nsfw && this.size !== 'hide'\n },\n useDescription () {\n return this.card.description && /\\S/.test(this.card.description)\n }\n },\n created () {\n if (this.useImage) {\n const newImg = new Image()\n newImg.onload = () => {\n this.imageLoaded = true\n }\n newImg.src = this.card.image\n }\n }\n}\n\nexport default LinkPreview\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./link-preview.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./link-preview.js\"\nimport __vue_script__ from \"!!babel-loader!./link-preview.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-7c8d99ac\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./link-preview.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',[_c('a',{staticClass:\"link-preview-card\",attrs:{\"href\":_vm.card.url,\"target\":\"_blank\",\"rel\":\"noopener\"}},[(_vm.useImage && _vm.imageLoaded)?_c('div',{staticClass:\"card-image\",class:{ 'small-image': _vm.size === 'small' }},[_c('img',{attrs:{\"src\":_vm.card.image}})]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"card-content\"},[_c('span',{staticClass:\"card-host faint\"},[_vm._v(_vm._s(_vm.card.provider_name))]),_vm._v(\" \"),_c('h4',{staticClass:\"card-title\"},[_vm._v(_vm._s(_vm.card.title))]),_vm._v(\" \"),(_vm.useDescription)?_c('p',{staticClass:\"card-description\"},[_vm._v(_vm._s(_vm.card.description))]):_vm._e()])])])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Attachment from '../attachment/attachment.vue'\nimport Poll from '../poll/poll.vue'\nimport Gallery from '../gallery/gallery.vue'\nimport LinkPreview from '../link-preview/link-preview.vue'\nimport generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'\nimport fileType from 'src/services/file_type/file_type.service'\nimport { processHtml } from 'src/services/tiny_post_html_processor/tiny_post_html_processor.service.js'\nimport { mentionMatchesUrl, extractTagFromUrl } from 'src/services/matcher/matcher.service.js'\nimport { mapGetters, mapState } from 'vuex'\n\nconst StatusContent = {\n name: 'StatusContent',\n props: [\n 'status',\n 'focused',\n 'noHeading',\n 'fullContent'\n ],\n data () {\n return {\n showingTall: this.inConversation && this.focused,\n showingLongSubject: false,\n // not as computed because it sets the initial state which will be changed later\n expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject\n }\n },\n computed: {\n localCollapseSubjectDefault () {\n return this.mergedConfig.collapseMessageWithSubject\n },\n hideAttachments () {\n return (this.mergedConfig.hideAttachments && !this.inConversation) ||\n (this.mergedConfig.hideAttachmentsInConv && this.inConversation)\n },\n // This is a bit hacky, but we want to approximate post height before rendering\n // so we count newlines (masto uses

for paragraphs, GS uses
between them)\n // as well as approximate line count by counting characters and approximating ~80\n // per line.\n //\n // Using max-height + overflow: auto for status components resulted in false positives\n // very often with japanese characters, and it was very annoying.\n tallStatus () {\n const lengthScore = this.status.statusnet_html.split(/ 20\n },\n longSubject () {\n return this.status.summary.length > 900\n },\n // When a status has a subject and is also tall, we should only have one show more/less button. If the default is to collapse statuses with subjects, we just treat it like a status with a subject; otherwise, we just treat it like a tall status.\n mightHideBecauseSubject () {\n return this.status.summary && (!this.tallStatus || this.localCollapseSubjectDefault)\n },\n mightHideBecauseTall () {\n return this.tallStatus && (!this.status.summary || !this.localCollapseSubjectDefault)\n },\n hideSubjectStatus () {\n return this.mightHideBecauseSubject && !this.expandingSubject\n },\n hideTallStatus () {\n return this.mightHideBecauseTall && !this.showingTall\n },\n showingMore () {\n return (this.mightHideBecauseTall && this.showingTall) || (this.mightHideBecauseSubject && this.expandingSubject)\n },\n nsfwClickthrough () {\n if (!this.status.nsfw) {\n return false\n }\n if (this.status.summary && this.localCollapseSubjectDefault) {\n return false\n }\n return true\n },\n attachmentSize () {\n if ((this.mergedConfig.hideAttachments && !this.inConversation) ||\n (this.mergedConfig.hideAttachmentsInConv && this.inConversation) ||\n (this.status.attachments.length > this.maxThumbnails)) {\n return 'hide'\n } else if (this.compact) {\n return 'small'\n }\n return 'normal'\n },\n galleryTypes () {\n if (this.attachmentSize === 'hide') {\n return []\n }\n return this.mergedConfig.playVideosInModal\n ? ['image', 'video']\n : ['image']\n },\n galleryAttachments () {\n return this.status.attachments.filter(\n file => fileType.fileMatchesSomeType(this.galleryTypes, file)\n )\n },\n nonGalleryAttachments () {\n return this.status.attachments.filter(\n file => !fileType.fileMatchesSomeType(this.galleryTypes, file)\n )\n },\n hasImageAttachments () {\n return this.status.attachments.some(\n file => fileType.fileType(file.mimetype) === 'image'\n )\n },\n hasVideoAttachments () {\n return this.status.attachments.some(\n file => fileType.fileType(file.mimetype) === 'video'\n )\n },\n maxThumbnails () {\n return this.mergedConfig.maxThumbnails\n },\n postBodyHtml () {\n const html = this.status.statusnet_html\n\n if (this.mergedConfig.greentext) {\n try {\n if (html.includes('>')) {\n // This checks if post has '>' at the beginning, excluding mentions so that @mention >impying works\n return processHtml(html, (string) => {\n if (string.includes('>') &&\n string\n .replace(/<[^>]+?>/gi, '') // remove all tags\n .replace(/@\\w+/gi, '') // remove mentions (even failed ones)\n .trim()\n .startsWith('>')) {\n return `${string}`\n } else {\n return string\n }\n })\n } else {\n return html\n }\n } catch (e) {\n console.err('Failed to process status html', e)\n return html\n }\n } else {\n return html\n }\n },\n contentHtml () {\n if (!this.status.summary_html) {\n return this.postBodyHtml\n }\n return this.status.summary_html + '
' + this.postBodyHtml\n },\n ...mapGetters(['mergedConfig']),\n ...mapState({\n betterShadow: state => state.interface.browserSupport.cssFilter,\n currentUser: state => state.users.currentUser\n })\n },\n components: {\n Attachment,\n Poll,\n Gallery,\n LinkPreview\n },\n methods: {\n linkClicked (event) {\n const target = event.target.closest('.status-content a')\n if (target) {\n if (target.className.match(/mention/)) {\n const href = target.href\n const attn = this.status.attentions.find(attn => mentionMatchesUrl(attn, href))\n if (attn) {\n event.stopPropagation()\n event.preventDefault()\n const link = this.generateUserProfileLink(attn.id, attn.screen_name)\n this.$router.push(link)\n return\n }\n }\n if (target.rel.match(/(?:^|\\s)tag(?:$|\\s)/) || target.className.match(/hashtag/)) {\n // Extract tag name from link url\n const tag = extractTagFromUrl(target.href)\n if (tag) {\n const link = this.generateTagLink(tag)\n this.$router.push(link)\n return\n }\n }\n window.open(target.href, '_blank')\n }\n },\n toggleShowMore () {\n if (this.mightHideBecauseTall) {\n this.showingTall = !this.showingTall\n } else if (this.mightHideBecauseSubject) {\n this.expandingSubject = !this.expandingSubject\n }\n },\n generateUserProfileLink (id, name) {\n return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)\n },\n generateTagLink (tag) {\n return `/tag/${tag}`\n },\n setMedia () {\n const attachments = this.attachmentSize === 'hide' ? this.status.attachments : this.galleryAttachments\n return () => this.$store.dispatch('setMedia', attachments)\n }\n }\n}\n\nexport default StatusContent\n","/**\n * This is a tiny purpose-built HTML parser/processor. This basically detects any type of visual newline and\n * allows it to be processed, useful for greentexting, mostly\n *\n * known issue: doesn't handle CDATA so nested CDATA might not work well\n *\n * @param {Object} input - input data\n * @param {(string) => string} processor - function that will be called on every line\n * @return {string} processed html\n */\nexport const processHtml = (html, processor) => {\n const handledTags = new Set(['p', 'br', 'div'])\n const openCloseTags = new Set(['p', 'div'])\n\n let buffer = '' // Current output buffer\n const level = [] // How deep we are in tags and which tags were there\n let textBuffer = '' // Current line content\n let tagBuffer = null // Current tag buffer, if null = we are not currently reading a tag\n\n // Extracts tag name from tag, i.e. => span\n const getTagName = (tag) => {\n const result = /(?:<\\/(\\w+)>|<(\\w+)\\s?[^/]*?\\/?>)/gi.exec(tag)\n return result && (result[1] || result[2])\n }\n\n const flush = () => { // Processes current line buffer, adds it to output buffer and clears line buffer\n if (textBuffer.trim().length > 0) {\n buffer += processor(textBuffer)\n } else {\n buffer += textBuffer\n }\n textBuffer = ''\n }\n\n const handleBr = (tag) => { // handles single newlines/linebreaks/selfclosing\n flush()\n buffer += tag\n }\n\n const handleOpen = (tag) => { // handles opening tags\n flush()\n buffer += tag\n level.push(tag)\n }\n\n const handleClose = (tag) => { // handles closing tags\n flush()\n buffer += tag\n if (level[level.length - 1] === tag) {\n level.pop()\n }\n }\n\n for (let i = 0; i < html.length; i++) {\n const char = html[i]\n if (char === '<' && tagBuffer === null) {\n tagBuffer = char\n } else if (char !== '>' && tagBuffer !== null) {\n tagBuffer += char\n } else if (char === '>' && tagBuffer !== null) {\n tagBuffer += char\n const tagFull = tagBuffer\n tagBuffer = null\n const tagName = getTagName(tagFull)\n if (handledTags.has(tagName)) {\n if (tagName === 'br') {\n handleBr(tagFull)\n } else if (openCloseTags.has(tagName)) {\n if (tagFull[1] === '/') {\n handleClose(tagFull)\n } else if (tagFull[tagFull.length - 2] === '/') {\n // self-closing\n handleBr(tagFull)\n } else {\n handleOpen(tagFull)\n }\n }\n } else {\n textBuffer += tagFull\n }\n } else if (char === '\\n') {\n handleBr(char)\n } else {\n textBuffer += char\n }\n }\n if (tagBuffer) {\n textBuffer += tagBuffer\n }\n\n flush()\n\n return buffer\n}\n","export const mentionMatchesUrl = (attention, url) => {\n if (url === attention.statusnet_profile_url) {\n return true\n }\n const [namepart, instancepart] = attention.screen_name.split('@')\n const matchstring = new RegExp('://' + instancepart + '/.*' + namepart + '$', 'g')\n\n return !!url.match(matchstring)\n}\n\n/**\n * Extract tag name from pleroma or mastodon url.\n * i.e https://bikeshed.party/tag/photo or https://quey.org/tags/sky\n * @param {string} url\n */\nexport const extractTagFromUrl = (url) => {\n const regex = /tag[s]*\\/(\\w+)$/g\n const result = regex.exec(url)\n if (!result) {\n return false\n }\n return result[1]\n}\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./status_content.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./status_content.js\"\nimport __vue_script__ from \"!!babel-loader!./status_content.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-43c5cfd4\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./status_content.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"status-body\"},[_vm._t(\"header\"),_vm._v(\" \"),(_vm.longSubject)?_c('div',{staticClass:\"status-content-wrapper\",class:{ 'tall-status': !_vm.showingLongSubject }},[(!_vm.showingLongSubject)?_c('a',{staticClass:\"tall-status-hider\",class:{ 'tall-status-hider_focused': _vm.focused },attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();_vm.showingLongSubject=true}}},[_vm._v(\"\\n \"+_vm._s(_vm.$t(\"general.show_more\"))+\"\\n \"),(_vm.hasImageAttachments)?_c('span',{staticClass:\"icon-picture\"}):_vm._e(),_vm._v(\" \"),(_vm.hasVideoAttachments)?_c('span',{staticClass:\"icon-video\"}):_vm._e(),_vm._v(\" \"),(_vm.status.card)?_c('span',{staticClass:\"icon-link\"}):_vm._e()]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"status-content media-body\",domProps:{\"innerHTML\":_vm._s(_vm.contentHtml)},on:{\"click\":function($event){$event.preventDefault();return _vm.linkClicked($event)}}}),_vm._v(\" \"),(_vm.showingLongSubject)?_c('a',{staticClass:\"status-unhider\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();_vm.showingLongSubject=false}}},[_vm._v(_vm._s(_vm.$t(\"general.show_less\")))]):_vm._e()]):_c('div',{staticClass:\"status-content-wrapper\",class:{'tall-status': _vm.hideTallStatus}},[(_vm.hideTallStatus)?_c('a',{staticClass:\"tall-status-hider\",class:{ 'tall-status-hider_focused': _vm.focused },attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleShowMore($event)}}},[_vm._v(_vm._s(_vm.$t(\"general.show_more\")))]):_vm._e(),_vm._v(\" \"),(!_vm.hideSubjectStatus)?_c('div',{staticClass:\"status-content media-body\",domProps:{\"innerHTML\":_vm._s(_vm.contentHtml)},on:{\"click\":function($event){$event.preventDefault();return _vm.linkClicked($event)}}}):_c('div',{staticClass:\"status-content media-body\",domProps:{\"innerHTML\":_vm._s(_vm.status.summary_html)},on:{\"click\":function($event){$event.preventDefault();return _vm.linkClicked($event)}}}),_vm._v(\" \"),(_vm.hideSubjectStatus)?_c('a',{staticClass:\"cw-status-hider\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleShowMore($event)}}},[_vm._v(_vm._s(_vm.$t(\"general.show_more\")))]):_vm._e(),_vm._v(\" \"),(_vm.showingMore)?_c('a',{staticClass:\"status-unhider\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleShowMore($event)}}},[_vm._v(_vm._s(_vm.$t(\"general.show_less\")))]):_vm._e()]),_vm._v(\" \"),(_vm.status.poll && _vm.status.poll.options)?_c('div',[_c('poll',{attrs:{\"base-poll\":_vm.status.poll}})],1):_vm._e(),_vm._v(\" \"),(_vm.status.attachments.length !== 0 && (!_vm.hideSubjectStatus || _vm.showingLongSubject))?_c('div',{staticClass:\"attachments media-body\"},[_vm._l((_vm.nonGalleryAttachments),function(attachment){return _c('attachment',{key:attachment.id,staticClass:\"non-gallery\",attrs:{\"size\":_vm.attachmentSize,\"nsfw\":_vm.nsfwClickthrough,\"attachment\":attachment,\"allow-play\":true,\"set-media\":_vm.setMedia()}})}),_vm._v(\" \"),(_vm.galleryAttachments.length > 0)?_c('gallery',{attrs:{\"nsfw\":_vm.nsfwClickthrough,\"attachments\":_vm.galleryAttachments,\"set-media\":_vm.setMedia()}}):_vm._e()],2):_vm._e(),_vm._v(\" \"),(_vm.status.card && !_vm.hideSubjectStatus && !_vm.noHeading)?_c('div',{staticClass:\"link-preview media-body\"},[_c('link-preview',{attrs:{\"card\":_vm.status.card,\"size\":_vm.attachmentSize,\"nsfw\":_vm.nsfwClickthrough}})],1):_vm._e(),_vm._v(\" \"),_vm._t(\"footer\")],2)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import { find } from 'lodash'\n\nconst StatusPopover = {\n name: 'StatusPopover',\n props: [\n 'statusId'\n ],\n data () {\n return {\n error: false\n }\n },\n computed: {\n status () {\n return find(this.$store.state.statuses.allStatuses, { id: this.statusId })\n }\n },\n components: {\n Status: () => import('../status/status.vue'),\n Popover: () => import('../popover/popover.vue')\n },\n methods: {\n enter () {\n if (!this.status) {\n this.$store.dispatch('fetchStatus', this.statusId)\n .then(data => (this.error = false))\n .catch(e => (this.error = true))\n }\n }\n }\n}\n\nexport default StatusPopover\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./status_popover.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./status_popover.js\"\nimport __vue_script__ from \"!!babel-loader!./status_popover.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-3b873076\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./status_popover.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('Popover',{attrs:{\"trigger\":\"hover\",\"popover-class\":\"status-popover\",\"bound-to\":{ x: 'container' }},on:{\"show\":_vm.enter}},[_c('template',{slot:\"trigger\"},[_vm._t(\"default\")],2),_vm._v(\" \"),_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[(_vm.status)?_c('Status',{attrs:{\"is-preview\":true,\"statusoid\":_vm.status,\"compact\":true}}):(_vm.error)?_c('div',{staticClass:\"status-preview-no-content faint\"},[_vm._v(\"\\n \"+_vm._s(_vm.$t('status.status_unavailable'))+\"\\n \")]):_c('div',{staticClass:\"status-preview-no-content\"},[_c('i',{staticClass:\"icon-spin4 animate-spin\"})])],1)],2)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import UserAvatar from '../user_avatar/user_avatar.vue'\nimport Popover from '../popover/popover.vue'\n\nconst EMOJI_REACTION_COUNT_CUTOFF = 12\n\nconst EmojiReactions = {\n name: 'EmojiReactions',\n components: {\n UserAvatar,\n Popover\n },\n props: ['status'],\n data: () => ({\n showAll: false\n }),\n computed: {\n tooManyReactions () {\n return this.status.emoji_reactions.length > EMOJI_REACTION_COUNT_CUTOFF\n },\n emojiReactions () {\n return this.showAll\n ? this.status.emoji_reactions\n : this.status.emoji_reactions.slice(0, EMOJI_REACTION_COUNT_CUTOFF)\n },\n showMoreString () {\n return `+${this.status.emoji_reactions.length - EMOJI_REACTION_COUNT_CUTOFF}`\n },\n accountsForEmoji () {\n return this.status.emoji_reactions.reduce((acc, reaction) => {\n acc[reaction.name] = reaction.accounts || []\n return acc\n }, {})\n },\n loggedIn () {\n return !!this.$store.state.users.currentUser\n }\n },\n methods: {\n toggleShowAll () {\n this.showAll = !this.showAll\n },\n reactedWith (emoji) {\n return this.status.emoji_reactions.find(r => r.name === emoji).me\n },\n fetchEmojiReactionsByIfMissing () {\n const hasNoAccounts = this.status.emoji_reactions.find(r => !r.accounts)\n if (hasNoAccounts) {\n this.$store.dispatch('fetchEmojiReactionsBy', this.status.id)\n }\n },\n reactWith (emoji) {\n this.$store.dispatch('reactWithEmoji', { id: this.status.id, emoji })\n },\n unreact (emoji) {\n this.$store.dispatch('unreactWithEmoji', { id: this.status.id, emoji })\n },\n emojiOnClick (emoji, event) {\n if (!this.loggedIn) return\n\n if (this.reactedWith(emoji)) {\n this.unreact(emoji)\n } else {\n this.reactWith(emoji)\n }\n }\n }\n}\n\nexport default EmojiReactions\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./emoji_reactions.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./emoji_reactions.js\"\nimport __vue_script__ from \"!!babel-loader!./emoji_reactions.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-09ec7fb6\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./emoji_reactions.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"emoji-reactions\"},[_vm._l((_vm.emojiReactions),function(reaction){return _c('Popover',{key:reaction.name,attrs:{\"trigger\":\"hover\",\"placement\":\"top\",\"offset\":{ y: 5 }}},[_c('div',{staticClass:\"reacted-users\",attrs:{\"slot\":\"content\"},slot:\"content\"},[(_vm.accountsForEmoji[reaction.name].length)?_c('div',_vm._l((_vm.accountsForEmoji[reaction.name]),function(account){return _c('div',{key:account.id,staticClass:\"reacted-user\"},[_c('UserAvatar',{staticClass:\"avatar-small\",attrs:{\"user\":account,\"compact\":true}}),_vm._v(\" \"),_c('div',{staticClass:\"reacted-user-names\"},[_c('span',{staticClass:\"reacted-user-name\",domProps:{\"innerHTML\":_vm._s(account.name_html)}}),_vm._v(\" \"),_c('span',{staticClass:\"reacted-user-screen-name\"},[_vm._v(_vm._s(account.screen_name))])])],1)}),0):_c('div',[_c('i',{staticClass:\"icon-spin4 animate-spin\"})])]),_vm._v(\" \"),_c('button',{staticClass:\"emoji-reaction btn btn-default\",class:{ 'picked-reaction': _vm.reactedWith(reaction.name), 'not-clickable': !_vm.loggedIn },attrs:{\"slot\":\"trigger\"},on:{\"click\":function($event){return _vm.emojiOnClick(reaction.name, $event)},\"mouseenter\":function($event){return _vm.fetchEmojiReactionsByIfMissing()}},slot:\"trigger\"},[_c('span',{staticClass:\"reaction-emoji\"},[_vm._v(_vm._s(reaction.name))]),_vm._v(\" \"),_c('span',[_vm._v(_vm._s(reaction.count))])])])}),_vm._v(\" \"),(_vm.tooManyReactions)?_c('a',{staticClass:\"emoji-reaction-expand faint\",attrs:{\"href\":\"javascript:void(0)\"},on:{\"click\":_vm.toggleShowAll}},[_vm._v(\"\\n \"+_vm._s(_vm.showAll ? _vm.$t('general.show_less') : _vm.showMoreString)+\"\\n \")]):_vm._e()],2)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import FavoriteButton from '../favorite_button/favorite_button.vue'\nimport ReactButton from '../react_button/react_button.vue'\nimport RetweetButton from '../retweet_button/retweet_button.vue'\nimport ExtraButtons from '../extra_buttons/extra_buttons.vue'\nimport PostStatusForm from '../post_status_form/post_status_form.vue'\nimport UserCard from '../user_card/user_card.vue'\nimport UserAvatar from '../user_avatar/user_avatar.vue'\nimport AvatarList from '../avatar_list/avatar_list.vue'\nimport Timeago from '../timeago/timeago.vue'\nimport StatusContent from '../status_content/status_content.vue'\nimport StatusPopover from '../status_popover/status_popover.vue'\nimport EmojiReactions from '../emoji_reactions/emoji_reactions.vue'\nimport generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'\nimport { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'\nimport { filter, unescape, uniqBy } from 'lodash'\nimport { mapGetters, mapState } from 'vuex'\n\nconst Status = {\n name: 'Status',\n props: [\n 'statusoid',\n 'expandable',\n 'inConversation',\n 'focused',\n 'highlight',\n 'compact',\n 'replies',\n 'isPreview',\n 'noHeading',\n 'inlineExpanded',\n 'showPinned',\n 'inProfile',\n 'profileUserId'\n ],\n data () {\n return {\n replying: false,\n unmuted: false,\n userExpanded: false,\n error: null\n }\n },\n computed: {\n muteWords () {\n return this.mergedConfig.muteWords\n },\n repeaterClass () {\n const user = this.statusoid.user\n return highlightClass(user)\n },\n userClass () {\n const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user\n return highlightClass(user)\n },\n deleted () {\n return this.statusoid.deleted\n },\n repeaterStyle () {\n const user = this.statusoid.user\n const highlight = this.mergedConfig.highlight\n return highlightStyle(highlight[user.screen_name])\n },\n userStyle () {\n if (this.noHeading) return\n const user = this.retweet ? (this.statusoid.retweeted_status.user) : this.statusoid.user\n const highlight = this.mergedConfig.highlight\n return highlightStyle(highlight[user.screen_name])\n },\n userProfileLink () {\n return this.generateUserProfileLink(this.status.user.id, this.status.user.screen_name)\n },\n replyProfileLink () {\n if (this.isReply) {\n return this.generateUserProfileLink(this.status.in_reply_to_user_id, this.replyToName)\n }\n },\n retweet () { return !!this.statusoid.retweeted_status },\n retweeter () { return this.statusoid.user.name || this.statusoid.user.screen_name },\n retweeterHtml () { return this.statusoid.user.name_html },\n retweeterProfileLink () { return this.generateUserProfileLink(this.statusoid.user.id, this.statusoid.user.screen_name) },\n status () {\n if (this.retweet) {\n return this.statusoid.retweeted_status\n } else {\n return this.statusoid\n }\n },\n statusFromGlobalRepository () {\n // NOTE: Consider to replace status with statusFromGlobalRepository\n return this.$store.state.statuses.allStatusesObject[this.status.id]\n },\n loggedIn () {\n return !!this.currentUser\n },\n muteWordHits () {\n const statusText = this.status.text.toLowerCase()\n const statusSummary = this.status.summary.toLowerCase()\n const hits = filter(this.muteWords, (muteWord) => {\n return statusText.includes(muteWord.toLowerCase()) || statusSummary.includes(muteWord.toLowerCase())\n })\n\n return hits\n },\n muted () {\n const relationship = this.$store.getters.relationship(this.status.user.id)\n return !this.unmuted && (\n (!(this.inProfile && this.status.user.id === this.profileUserId) && relationship.muting) ||\n (!this.inConversation && this.status.thread_muted) ||\n this.muteWordHits.length > 0)\n },\n hideFilteredStatuses () {\n return this.mergedConfig.hideFilteredStatuses\n },\n hideStatus () {\n return (this.hideReply || this.deleted) || (this.muted && this.hideFilteredStatuses)\n },\n isFocused () {\n // retweet or root of an expanded conversation\n if (this.focused) {\n return true\n } else if (!this.inConversation) {\n return false\n }\n // use conversation highlight only when in conversation\n return this.status.id === this.highlight\n },\n isReply () {\n return !!(this.status.in_reply_to_status_id && this.status.in_reply_to_user_id)\n },\n replyToName () {\n if (this.status.in_reply_to_screen_name) {\n return this.status.in_reply_to_screen_name\n } else {\n const user = this.$store.getters.findUser(this.status.in_reply_to_user_id)\n return user && user.screen_name\n }\n },\n hideReply () {\n if (this.mergedConfig.replyVisibility === 'all') {\n return false\n }\n if (this.inConversation || !this.isReply) {\n return false\n }\n if (this.status.user.id === this.currentUser.id) {\n return false\n }\n if (this.status.type === 'retweet') {\n return false\n }\n const checkFollowing = this.mergedConfig.replyVisibility === 'following'\n for (var i = 0; i < this.status.attentions.length; ++i) {\n if (this.status.user.id === this.status.attentions[i].id) {\n continue\n }\n // There's zero guarantee of this working. If we happen to have that user and their\n // relationship in store then it will work, but there's kinda little chance of having\n // them for people you're not following.\n const relationship = this.$store.state.users.relationships[this.status.attentions[i].id]\n if (checkFollowing && relationship && relationship.following) {\n return false\n }\n if (this.status.attentions[i].id === this.currentUser.id) {\n return false\n }\n }\n return this.status.attentions.length > 0\n },\n replySubject () {\n if (!this.status.summary) return ''\n const decodedSummary = unescape(this.status.summary)\n const behavior = this.mergedConfig.subjectLineBehavior\n const startsWithRe = decodedSummary.match(/^re[: ]/i)\n if ((behavior !== 'noop' && startsWithRe) || behavior === 'masto') {\n return decodedSummary\n } else if (behavior === 'email') {\n return 're: '.concat(decodedSummary)\n } else if (behavior === 'noop') {\n return ''\n }\n },\n combinedFavsAndRepeatsUsers () {\n // Use the status from the global status repository since favs and repeats are saved in it\n const combinedUsers = [].concat(\n this.statusFromGlobalRepository.favoritedBy,\n this.statusFromGlobalRepository.rebloggedBy\n )\n return uniqBy(combinedUsers, 'id')\n },\n tags () {\n return this.status.tags.filter(tagObj => tagObj.hasOwnProperty('name')).map(tagObj => tagObj.name).join(' ')\n },\n hidePostStats () {\n return this.mergedConfig.hidePostStats\n },\n ...mapGetters(['mergedConfig']),\n ...mapState({\n betterShadow: state => state.interface.browserSupport.cssFilter,\n currentUser: state => state.users.currentUser\n })\n },\n components: {\n FavoriteButton,\n ReactButton,\n RetweetButton,\n ExtraButtons,\n PostStatusForm,\n UserCard,\n UserAvatar,\n AvatarList,\n Timeago,\n StatusPopover,\n EmojiReactions,\n StatusContent\n },\n methods: {\n visibilityIcon (visibility) {\n switch (visibility) {\n case 'private':\n return 'icon-lock'\n case 'unlisted':\n return 'icon-lock-open-alt'\n case 'direct':\n return 'icon-mail-alt'\n default:\n return 'icon-globe'\n }\n },\n showError (error) {\n this.error = error\n },\n clearError () {\n this.error = undefined\n },\n toggleReplying () {\n this.replying = !this.replying\n },\n gotoOriginal (id) {\n if (this.inConversation) {\n this.$emit('goto', id)\n }\n },\n toggleExpanded () {\n this.$emit('toggleExpanded')\n },\n toggleMute () {\n this.unmuted = !this.unmuted\n },\n toggleUserExpanded () {\n this.userExpanded = !this.userExpanded\n },\n generateUserProfileLink (id, name) {\n return generateProfileLink(id, name, this.$store.state.instance.restrictedNicknames)\n }\n },\n watch: {\n 'highlight': function (id) {\n if (this.status.id === id) {\n let rect = this.$el.getBoundingClientRect()\n if (rect.top < 100) {\n // Post is above screen, match its top to screen top\n window.scrollBy(0, rect.top - 100)\n } else if (rect.height >= (window.innerHeight - 50)) {\n // Post we want to see is taller than screen so match its top to screen top\n window.scrollBy(0, rect.top - 100)\n } else if (rect.bottom > window.innerHeight - 50) {\n // Post is below screen, match its bottom to screen bottom\n window.scrollBy(0, rect.bottom - window.innerHeight + 50)\n }\n }\n },\n 'status.repeat_num': function (num) {\n // refetch repeats when repeat_num is changed in any way\n if (this.isFocused && this.statusFromGlobalRepository.rebloggedBy && this.statusFromGlobalRepository.rebloggedBy.length !== num) {\n this.$store.dispatch('fetchRepeats', this.status.id)\n }\n },\n 'status.fave_num': function (num) {\n // refetch favs when fave_num is changed in any way\n if (this.isFocused && this.statusFromGlobalRepository.favoritedBy && this.statusFromGlobalRepository.favoritedBy.length !== num) {\n this.$store.dispatch('fetchFavs', this.status.id)\n }\n }\n },\n filters: {\n capitalize: function (str) {\n return str.charAt(0).toUpperCase() + str.slice(1)\n }\n }\n}\n\nexport default Status\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./status.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./status.js\"\nimport __vue_script__ from \"!!babel-loader!./status.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-2d68efa0\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./status.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (!_vm.hideStatus)?_c('div',{staticClass:\"status-el\",class:[{ 'status-el_focused': _vm.isFocused }, { 'status-conversation': _vm.inlineExpanded }]},[(_vm.error)?_c('div',{staticClass:\"alert error\"},[_vm._v(\"\\n \"+_vm._s(_vm.error)+\"\\n \"),_c('i',{staticClass:\"button-icon icon-cancel\",on:{\"click\":_vm.clearError}})]):_vm._e(),_vm._v(\" \"),(_vm.muted && !_vm.isPreview)?[_c('div',{staticClass:\"media status container muted\"},[_c('small',[_c('router-link',{attrs:{\"to\":_vm.userProfileLink}},[_vm._v(\"\\n \"+_vm._s(_vm.status.user.screen_name)+\"\\n \")])],1),_vm._v(\" \"),_c('small',{staticClass:\"muteWords\"},[_vm._v(_vm._s(_vm.muteWordHits.join(', ')))]),_vm._v(\" \"),_c('a',{staticClass:\"unmute\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleMute($event)}}},[_c('i',{staticClass:\"button-icon icon-eye-off\"})])])]:[(_vm.showPinned)?_c('div',{staticClass:\"status-pin\"},[_c('i',{staticClass:\"fa icon-pin faint\"}),_vm._v(\" \"),_c('span',{staticClass:\"faint\"},[_vm._v(_vm._s(_vm.$t('status.pinned')))])]):_vm._e(),_vm._v(\" \"),(_vm.retweet && !_vm.noHeading && !_vm.inConversation)?_c('div',{staticClass:\"media container retweet-info\",class:[_vm.repeaterClass, { highlighted: _vm.repeaterStyle }],style:([_vm.repeaterStyle])},[(_vm.retweet)?_c('UserAvatar',{staticClass:\"media-left\",attrs:{\"better-shadow\":_vm.betterShadow,\"user\":_vm.statusoid.user}}):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"media-body faint\"},[_c('span',{staticClass:\"user-name\"},[(_vm.retweeterHtml)?_c('router-link',{attrs:{\"to\":_vm.retweeterProfileLink},domProps:{\"innerHTML\":_vm._s(_vm.retweeterHtml)}}):_c('router-link',{attrs:{\"to\":_vm.retweeterProfileLink}},[_vm._v(_vm._s(_vm.retweeter))])],1),_vm._v(\" \"),_c('i',{staticClass:\"fa icon-retweet retweeted\",attrs:{\"title\":_vm.$t('tool_tip.repeat')}}),_vm._v(\"\\n \"+_vm._s(_vm.$t('timeline.repeated'))+\"\\n \")])],1):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"media status\",class:[_vm.userClass, { highlighted: _vm.userStyle, 'is-retweet': _vm.retweet && !_vm.inConversation }],style:([ _vm.userStyle ]),attrs:{\"data-tags\":_vm.tags}},[(!_vm.noHeading)?_c('div',{staticClass:\"media-left\"},[_c('router-link',{attrs:{\"to\":_vm.userProfileLink},nativeOn:{\"!click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.toggleUserExpanded($event)}}},[_c('UserAvatar',{attrs:{\"compact\":_vm.compact,\"better-shadow\":_vm.betterShadow,\"user\":_vm.status.user}})],1)],1):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"status-body\"},[(_vm.userExpanded)?_c('UserCard',{staticClass:\"status-usercard\",attrs:{\"user-id\":_vm.status.user.id,\"rounded\":true,\"bordered\":true}}):_vm._e(),_vm._v(\" \"),(!_vm.noHeading)?_c('div',{staticClass:\"media-heading\"},[_c('div',{staticClass:\"heading-name-row\"},[_c('div',{staticClass:\"name-and-account-name\"},[(_vm.status.user.name_html)?_c('h4',{staticClass:\"user-name\",domProps:{\"innerHTML\":_vm._s(_vm.status.user.name_html)}}):_c('h4',{staticClass:\"user-name\"},[_vm._v(\"\\n \"+_vm._s(_vm.status.user.name)+\"\\n \")]),_vm._v(\" \"),_c('router-link',{staticClass:\"account-name\",attrs:{\"to\":_vm.userProfileLink}},[_vm._v(\"\\n \"+_vm._s(_vm.status.user.screen_name)+\"\\n \")])],1),_vm._v(\" \"),_c('span',{staticClass:\"heading-right\"},[_c('router-link',{staticClass:\"timeago faint-link\",attrs:{\"to\":{ name: 'conversation', params: { id: _vm.status.id } }}},[_c('Timeago',{attrs:{\"time\":_vm.status.created_at,\"auto-update\":60}})],1),_vm._v(\" \"),(_vm.status.visibility)?_c('div',{staticClass:\"button-icon visibility-icon\"},[_c('i',{class:_vm.visibilityIcon(_vm.status.visibility),attrs:{\"title\":_vm._f(\"capitalize\")(_vm.status.visibility)}})]):_vm._e(),_vm._v(\" \"),(!_vm.status.is_local && !_vm.isPreview)?_c('a',{staticClass:\"source_url\",attrs:{\"href\":_vm.status.external_url,\"target\":\"_blank\",\"title\":\"Source\"}},[_c('i',{staticClass:\"button-icon icon-link-ext-alt\"})]):_vm._e(),_vm._v(\" \"),(_vm.expandable && !_vm.isPreview)?[_c('a',{attrs:{\"href\":\"#\",\"title\":\"Expand\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleExpanded($event)}}},[_c('i',{staticClass:\"button-icon icon-plus-squared\"})])]:_vm._e(),_vm._v(\" \"),(_vm.unmuted)?_c('a',{attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleMute($event)}}},[_c('i',{staticClass:\"button-icon icon-eye-off\"})]):_vm._e()],2)]),_vm._v(\" \"),_c('div',{staticClass:\"heading-reply-row\"},[(_vm.isReply)?_c('div',{staticClass:\"reply-to-and-accountname\"},[(!_vm.isPreview)?_c('StatusPopover',{staticClass:\"reply-to-popover\",staticStyle:{\"min-width\":\"0\"},attrs:{\"status-id\":_vm.status.in_reply_to_status_id}},[_c('a',{staticClass:\"reply-to\",attrs:{\"href\":\"#\",\"aria-label\":_vm.$t('tool_tip.reply')},on:{\"click\":function($event){$event.preventDefault();return _vm.gotoOriginal(_vm.status.in_reply_to_status_id)}}},[_c('i',{staticClass:\"button-icon icon-reply\"}),_vm._v(\" \"),_c('span',{staticClass:\"faint-link reply-to-text\"},[_vm._v(_vm._s(_vm.$t('status.reply_to')))])])]):_c('span',{staticClass:\"reply-to\"},[_c('span',{staticClass:\"reply-to-text\"},[_vm._v(_vm._s(_vm.$t('status.reply_to')))])]),_vm._v(\" \"),_c('router-link',{attrs:{\"to\":_vm.replyProfileLink}},[_vm._v(\"\\n \"+_vm._s(_vm.replyToName)+\"\\n \")]),_vm._v(\" \"),(_vm.replies && _vm.replies.length)?_c('span',{staticClass:\"faint replies-separator\"},[_vm._v(\"\\n -\\n \")]):_vm._e()],1):_vm._e(),_vm._v(\" \"),(_vm.inConversation && !_vm.isPreview && _vm.replies && _vm.replies.length)?_c('div',{staticClass:\"replies\"},[_c('span',{staticClass:\"faint\"},[_vm._v(_vm._s(_vm.$t('status.replies_list')))]),_vm._v(\" \"),_vm._l((_vm.replies),function(reply){return _c('StatusPopover',{key:reply.id,attrs:{\"status-id\":reply.id}},[_c('a',{staticClass:\"reply-link\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();return _vm.gotoOriginal(reply.id)}}},[_vm._v(_vm._s(reply.name))])])})],2):_vm._e()])]):_vm._e(),_vm._v(\" \"),_c('StatusContent',{attrs:{\"status\":_vm.status,\"no-heading\":_vm.noHeading,\"highlight\":_vm.highlight,\"focused\":_vm.isFocused}}),_vm._v(\" \"),_c('transition',{attrs:{\"name\":\"fade\"}},[(!_vm.hidePostStats && _vm.isFocused && _vm.combinedFavsAndRepeatsUsers.length > 0)?_c('div',{staticClass:\"favs-repeated-users\"},[_c('div',{staticClass:\"stats\"},[(_vm.statusFromGlobalRepository.rebloggedBy && _vm.statusFromGlobalRepository.rebloggedBy.length > 0)?_c('div',{staticClass:\"stat-count\"},[_c('a',{staticClass:\"stat-title\"},[_vm._v(_vm._s(_vm.$t('status.repeats')))]),_vm._v(\" \"),_c('div',{staticClass:\"stat-number\"},[_vm._v(\"\\n \"+_vm._s(_vm.statusFromGlobalRepository.rebloggedBy.length)+\"\\n \")])]):_vm._e(),_vm._v(\" \"),(_vm.statusFromGlobalRepository.favoritedBy && _vm.statusFromGlobalRepository.favoritedBy.length > 0)?_c('div',{staticClass:\"stat-count\"},[_c('a',{staticClass:\"stat-title\"},[_vm._v(_vm._s(_vm.$t('status.favorites')))]),_vm._v(\" \"),_c('div',{staticClass:\"stat-number\"},[_vm._v(\"\\n \"+_vm._s(_vm.statusFromGlobalRepository.favoritedBy.length)+\"\\n \")])]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"avatar-row\"},[_c('AvatarList',{attrs:{\"users\":_vm.combinedFavsAndRepeatsUsers}})],1)])]):_vm._e()]),_vm._v(\" \"),((_vm.mergedConfig.emojiReactionsOnTimeline || _vm.isFocused) && (!_vm.noHeading && !_vm.isPreview))?_c('EmojiReactions',{attrs:{\"status\":_vm.status}}):_vm._e(),_vm._v(\" \"),(!_vm.noHeading && !_vm.isPreview)?_c('div',{staticClass:\"status-actions media-body\"},[_c('div',[(_vm.loggedIn)?_c('i',{staticClass:\"button-icon icon-reply\",class:{'button-icon-active': _vm.replying},attrs:{\"title\":_vm.$t('tool_tip.reply')},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleReplying($event)}}}):_c('i',{staticClass:\"button-icon button-icon-disabled icon-reply\",attrs:{\"title\":_vm.$t('tool_tip.reply')}}),_vm._v(\" \"),(_vm.status.replies_count > 0)?_c('span',[_vm._v(_vm._s(_vm.status.replies_count))]):_vm._e()]),_vm._v(\" \"),_c('retweet-button',{attrs:{\"visibility\":_vm.status.visibility,\"logged-in\":_vm.loggedIn,\"status\":_vm.status}}),_vm._v(\" \"),_c('favorite-button',{attrs:{\"logged-in\":_vm.loggedIn,\"status\":_vm.status}}),_vm._v(\" \"),(_vm.loggedIn)?_c('ReactButton',{attrs:{\"status\":_vm.status}}):_vm._e(),_vm._v(\" \"),_c('extra-buttons',{attrs:{\"status\":_vm.status},on:{\"onError\":_vm.showError,\"onSuccess\":_vm.clearError}})],1):_vm._e()],1)]),_vm._v(\" \"),(_vm.replying)?_c('div',{staticClass:\"container\"},[_c('PostStatusForm',{staticClass:\"reply-body\",attrs:{\"reply-to\":_vm.status.id,\"attentions\":_vm.status.attentions,\"replied-user\":_vm.status.user,\"copy-message-scope\":_vm.status.visibility,\"subject\":_vm.replySubject},on:{\"posted\":_vm.toggleReplying}})],1):_vm._e()]],2):_vm._e()}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","\nconst Popover = {\n name: 'Popover',\n props: {\n // Action to trigger popover: either 'hover' or 'click'\n trigger: String,\n // Either 'top' or 'bottom'\n placement: String,\n // Takes object with properties 'x' and 'y', values of these can be\n // 'container' for using offsetParent as boundaries for either axis\n // or 'viewport'\n boundTo: Object,\n // Takes a top/bottom/left/right object, how much space to leave\n // between boundary and popover element\n margin: Object,\n // Takes a x/y object and tells how many pixels to offset from\n // anchor point on either axis\n offset: Object,\n // Additional styles you may want for the popover container\n popoverClass: String\n },\n data () {\n return {\n hidden: true,\n styles: { opacity: 0 },\n oldSize: { width: 0, height: 0 }\n }\n },\n methods: {\n updateStyles () {\n if (this.hidden) {\n this.styles = {\n opacity: 0\n }\n return\n }\n\n // Popover will be anchored around this element, trigger ref is the container, so\n // its children are what are inside the slot. Expect only one slot=\"trigger\".\n const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el\n const screenBox = anchorEl.getBoundingClientRect()\n // Screen position of the origin point for popover\n const origin = { x: screenBox.left + screenBox.width * 0.5, y: screenBox.top }\n const content = this.$refs.content\n // Minor optimization, don't call a slow reflow call if we don't have to\n const parentBounds = this.boundTo &&\n (this.boundTo.x === 'container' || this.boundTo.y === 'container') &&\n this.$el.offsetParent.getBoundingClientRect()\n const margin = this.margin || {}\n\n // What are the screen bounds for the popover? Viewport vs container\n // when using viewport, using default margin values to dodge the navbar\n const xBounds = this.boundTo && this.boundTo.x === 'container' ? {\n min: parentBounds.left + (margin.left || 0),\n max: parentBounds.right - (margin.right || 0)\n } : {\n min: 0 + (margin.left || 10),\n max: window.innerWidth - (margin.right || 10)\n }\n\n const yBounds = this.boundTo && this.boundTo.y === 'container' ? {\n min: parentBounds.top + (margin.top || 0),\n max: parentBounds.bottom - (margin.bottom || 0)\n } : {\n min: 0 + (margin.top || 50),\n max: window.innerHeight - (margin.bottom || 5)\n }\n\n let horizOffset = 0\n\n // If overflowing from left, move it so that it doesn't\n if ((origin.x - content.offsetWidth * 0.5) < xBounds.min) {\n horizOffset += -(origin.x - content.offsetWidth * 0.5) + xBounds.min\n }\n\n // If overflowing from right, move it so that it doesn't\n if ((origin.x + horizOffset + content.offsetWidth * 0.5) > xBounds.max) {\n horizOffset -= (origin.x + horizOffset + content.offsetWidth * 0.5) - xBounds.max\n }\n\n // Default to whatever user wished with placement prop\n let usingTop = this.placement !== 'bottom'\n\n // Handle special cases, first force to displaying on top if there's not space on bottom,\n // regardless of what placement value was. Then check if there's not space on top, and\n // force to bottom, again regardless of what placement value was.\n if (origin.y + content.offsetHeight > yBounds.max) usingTop = true\n if (origin.y - content.offsetHeight < yBounds.min) usingTop = false\n\n const yOffset = (this.offset && this.offset.y) || 0\n const translateY = usingTop\n ? -anchorEl.offsetHeight - yOffset - content.offsetHeight\n : yOffset\n\n const xOffset = (this.offset && this.offset.x) || 0\n const translateX = (anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset\n\n // Note, separate translateX and translateY avoids blurry text on chromium,\n // single translate or translate3d resulted in blurry text.\n this.styles = {\n opacity: 1,\n transform: `translateX(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)`\n }\n },\n showPopover () {\n if (this.hidden) this.$emit('show')\n this.hidden = false\n this.$nextTick(this.updateStyles)\n },\n hidePopover () {\n if (!this.hidden) this.$emit('close')\n this.hidden = true\n this.styles = { opacity: 0 }\n },\n onMouseenter (e) {\n if (this.trigger === 'hover') this.showPopover()\n },\n onMouseleave (e) {\n if (this.trigger === 'hover') this.hidePopover()\n },\n onClick (e) {\n if (this.trigger === 'click') {\n if (this.hidden) {\n this.showPopover()\n } else {\n this.hidePopover()\n }\n }\n },\n onClickOutside (e) {\n if (this.hidden) return\n if (this.$el.contains(e.target)) return\n this.hidePopover()\n }\n },\n updated () {\n // Monitor changes to content size, update styles only when content sizes have changed,\n // that should be the only time we need to move the popover box if we don't care about scroll\n // or resize\n const content = this.$refs.content\n if (!content) return\n if (this.oldSize.width !== content.offsetWidth || this.oldSize.height !== content.offsetHeight) {\n this.updateStyles()\n this.oldSize = { width: content.offsetWidth, height: content.offsetHeight }\n }\n },\n created () {\n document.addEventListener('click', this.onClickOutside)\n },\n destroyed () {\n document.removeEventListener('click', this.onClickOutside)\n this.hidePopover()\n }\n}\n\nexport default Popover\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./popover.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./popover.js\"\nimport __vue_script__ from \"!!babel-loader!./popover.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-10f1984d\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./popover.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{on:{\"mouseenter\":_vm.onMouseenter,\"mouseleave\":_vm.onMouseleave}},[_c('div',{ref:\"trigger\",on:{\"click\":_vm.onClick}},[_vm._t(\"trigger\")],2),_vm._v(\" \"),(!_vm.hidden)?_c('div',{ref:\"content\",staticClass:\"popover\",class:_vm.popoverClass,style:(_vm.styles)},[_vm._t(\"content\",null,{\"close\":_vm.hidePopover})],2):_vm._e()])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","export const SECOND = 1000\nexport const MINUTE = 60 * SECOND\nexport const HOUR = 60 * MINUTE\nexport const DAY = 24 * HOUR\nexport const WEEK = 7 * DAY\nexport const MONTH = 30 * DAY\nexport const YEAR = 365.25 * DAY\n\nexport const relativeTime = (date, nowThreshold = 1) => {\n if (typeof date === 'string') date = Date.parse(date)\n const round = Date.now() > date ? Math.floor : Math.ceil\n const d = Math.abs(Date.now() - date)\n let r = { num: round(d / YEAR), key: 'time.years' }\n if (d < nowThreshold * SECOND) {\n r.num = 0\n r.key = 'time.now'\n } else if (d < MINUTE) {\n r.num = round(d / SECOND)\n r.key = 'time.seconds'\n } else if (d < HOUR) {\n r.num = round(d / MINUTE)\n r.key = 'time.minutes'\n } else if (d < DAY) {\n r.num = round(d / HOUR)\n r.key = 'time.hours'\n } else if (d < WEEK) {\n r.num = round(d / DAY)\n r.key = 'time.days'\n } else if (d < MONTH) {\n r.num = round(d / WEEK)\n r.key = 'time.weeks'\n } else if (d < YEAR) {\n r.num = round(d / MONTH)\n r.key = 'time.months'\n }\n // Remove plural form when singular\n if (r.num === 1) r.key = r.key.slice(0, -1)\n return r\n}\n\nexport const relativeTimeShort = (date, nowThreshold = 1) => {\n const r = relativeTime(date, nowThreshold)\n r.key += '_short'\n return r\n}\n","\n\n\n","/* script */\nexport * from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./progress_button.vue\"\nimport __vue_script__ from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./progress_button.vue\"\n/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-9f751ae6\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./progress_button.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = null\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('button',{attrs:{\"disabled\":_vm.progress || _vm.disabled},on:{\"click\":_vm.onClick}},[(_vm.progress && _vm.$slots.progress)?[_vm._t(\"progress\")]:[_vm._t(\"default\")]],2)}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import { hex2rgb } from '../color_convert/color_convert.js'\nconst highlightStyle = (prefs) => {\n if (prefs === undefined) return\n const { color, type } = prefs\n if (typeof color !== 'string') return\n const rgb = hex2rgb(color)\n if (rgb == null) return\n const solidColor = `rgb(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)})`\n const tintColor = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .1)`\n const tintColor2 = `rgba(${Math.floor(rgb.r)}, ${Math.floor(rgb.g)}, ${Math.floor(rgb.b)}, .2)`\n if (type === 'striped') {\n return {\n backgroundImage: [\n 'repeating-linear-gradient(135deg,',\n `${tintColor} ,`,\n `${tintColor} 20px,`,\n `${tintColor2} 20px,`,\n `${tintColor2} 40px`\n ].join(' '),\n backgroundPosition: '0 0'\n }\n } else if (type === 'solid') {\n return {\n backgroundColor: tintColor2\n }\n } else if (type === 'side') {\n return {\n backgroundImage: [\n 'linear-gradient(to right,',\n `${solidColor} ,`,\n `${solidColor} 2px,`,\n `transparent 6px`\n ].join(' '),\n backgroundPosition: '0 0'\n }\n }\n}\n\nconst highlightClass = (user) => {\n return 'USER____' + user.screen_name\n .replace(/\\./g, '_')\n .replace(/@/g, '_AT_')\n}\n\nexport {\n highlightClass,\n highlightStyle\n}\n","import Vue from 'vue'\n\nimport './tab_switcher.scss'\n\nexport default Vue.component('tab-switcher', {\n name: 'TabSwitcher',\n props: {\n renderOnlyFocused: {\n required: false,\n type: Boolean,\n default: false\n },\n onSwitch: {\n required: false,\n type: Function,\n default: undefined\n },\n activeTab: {\n required: false,\n type: String,\n default: undefined\n },\n scrollableTabs: {\n required: false,\n type: Boolean,\n default: false\n }\n },\n data () {\n return {\n active: this.$slots.default.findIndex(_ => _.tag)\n }\n },\n computed: {\n activeIndex () {\n // In case of controlled component\n if (this.activeTab) {\n return this.$slots.default.findIndex(slot => this.activeTab === slot.key)\n } else {\n return this.active\n }\n }\n },\n beforeUpdate () {\n const currentSlot = this.$slots.default[this.active]\n if (!currentSlot.tag) {\n this.active = this.$slots.default.findIndex(_ => _.tag)\n }\n },\n methods: {\n activateTab (index) {\n return (e) => {\n e.preventDefault()\n if (typeof this.onSwitch === 'function') {\n this.onSwitch.call(null, this.$slots.default[index].key)\n }\n this.active = index\n }\n }\n },\n render (h) {\n const tabs = this.$slots.default\n .map((slot, index) => {\n if (!slot.tag) return\n const classesTab = ['tab']\n const classesWrapper = ['tab-wrapper']\n\n if (this.activeIndex === index) {\n classesTab.push('active')\n classesWrapper.push('active')\n }\n if (slot.data.attrs.image) {\n return (\n

\n \n \n {slot.data.attrs.label ? '' : slot.data.attrs.label}\n \n
\n )\n }\n return (\n
\n \n {slot.data.attrs.label}\n
\n )\n })\n\n const contents = this.$slots.default.map((slot, index) => {\n if (!slot.tag) return\n const active = this.activeIndex === index\n if (this.renderOnlyFocused) {\n return active\n ?
{slot}
\n :
\n }\n return
{slot}
\n })\n\n return (\n
\n
\n {tabs}\n
\n
\n {contents}\n
\n
\n )\n }\n})\n","/* eslint-env browser */\nimport statusPosterService from '../../services/status_poster/status_poster.service.js'\nimport fileSizeFormatService from '../../services/file_size_format/file_size_format.js'\n\nconst mediaUpload = {\n data () {\n return {\n uploading: false,\n uploadReady: true\n }\n },\n methods: {\n uploadFile (file) {\n const self = this\n const store = this.$store\n if (file.size > store.state.instance.uploadlimit) {\n const filesize = fileSizeFormatService.fileSizeFormat(file.size)\n const allowedsize = fileSizeFormatService.fileSizeFormat(store.state.instance.uploadlimit)\n self.$emit('upload-failed', 'file_too_big', { filesize: filesize.num, filesizeunit: filesize.unit, allowedsize: allowedsize.num, allowedsizeunit: allowedsize.unit })\n return\n }\n const formData = new FormData()\n formData.append('file', file)\n\n self.$emit('uploading')\n self.uploading = true\n\n statusPosterService.uploadMedia({ store, formData })\n .then((fileData) => {\n self.$emit('uploaded', fileData)\n self.uploading = false\n }, (error) => { // eslint-disable-line handle-callback-err\n self.$emit('upload-failed', 'default')\n self.uploading = false\n })\n },\n fileDrop (e) {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault() // allow dropping text like before\n this.uploadFile(e.dataTransfer.files[0])\n }\n },\n fileDrag (e) {\n let types = e.dataTransfer.types\n if (types.contains('Files')) {\n e.dataTransfer.dropEffect = 'copy'\n } else {\n e.dataTransfer.dropEffect = 'none'\n }\n },\n clearFile () {\n this.uploadReady = false\n this.$nextTick(() => {\n this.uploadReady = true\n })\n },\n change ({ target }) {\n for (var i = 0; i < target.files.length; i++) {\n let file = target.files[i]\n this.uploadFile(file)\n }\n }\n },\n props: [\n 'dropFiles'\n ],\n watch: {\n 'dropFiles': function (fileInfos) {\n if (!this.uploading) {\n this.uploadFile(fileInfos[0])\n }\n }\n }\n}\n\nexport default mediaUpload\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./media_upload.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./media_upload.js\"\nimport __vue_script__ from \"!!babel-loader!./media_upload.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-74382032\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./media_upload.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"media-upload\",on:{\"drop\":[function($event){$event.preventDefault();},_vm.fileDrop],\"dragover\":function($event){$event.preventDefault();return _vm.fileDrag($event)}}},[_c('label',{staticClass:\"label\",attrs:{\"title\":_vm.$t('tool_tip.media_upload')}},[(_vm.uploading)?_c('i',{staticClass:\"progress-icon icon-spin4 animate-spin\"}):_vm._e(),_vm._v(\" \"),(!_vm.uploading)?_c('i',{staticClass:\"new-icon icon-upload\"}):_vm._e(),_vm._v(\" \"),(_vm.uploadReady)?_c('input',{staticStyle:{\"position\":\"fixed\",\"top\":\"-100em\"},attrs:{\"type\":\"file\",\"multiple\":\"true\"},on:{\"change\":_vm.change}}):_vm._e()])])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import * as DateUtils from 'src/services/date_utils/date_utils.js'\nimport { uniq } from 'lodash'\n\nexport default {\n name: 'PollForm',\n props: ['visible'],\n data: () => ({\n pollType: 'single',\n options: ['', ''],\n expiryAmount: 10,\n expiryUnit: 'minutes'\n }),\n computed: {\n pollLimits () {\n return this.$store.state.instance.pollLimits\n },\n maxOptions () {\n return this.pollLimits.max_options\n },\n maxLength () {\n return this.pollLimits.max_option_chars\n },\n expiryUnits () {\n const allUnits = ['minutes', 'hours', 'days']\n const expiry = this.convertExpiryFromUnit\n return allUnits.filter(\n unit => this.pollLimits.max_expiration >= expiry(unit, 1)\n )\n },\n minExpirationInCurrentUnit () {\n return Math.ceil(\n this.convertExpiryToUnit(\n this.expiryUnit,\n this.pollLimits.min_expiration\n )\n )\n },\n maxExpirationInCurrentUnit () {\n return Math.floor(\n this.convertExpiryToUnit(\n this.expiryUnit,\n this.pollLimits.max_expiration\n )\n )\n }\n },\n methods: {\n clear () {\n this.pollType = 'single'\n this.options = ['', '']\n this.expiryAmount = 10\n this.expiryUnit = 'minutes'\n },\n nextOption (index) {\n const element = this.$el.querySelector(`#poll-${index + 1}`)\n if (element) {\n element.focus()\n } else {\n // Try adding an option and try focusing on it\n const addedOption = this.addOption()\n if (addedOption) {\n this.$nextTick(function () {\n this.nextOption(index)\n })\n }\n }\n },\n addOption () {\n if (this.options.length < this.maxOptions) {\n this.options.push('')\n return true\n }\n return false\n },\n deleteOption (index, event) {\n if (this.options.length > 2) {\n this.options.splice(index, 1)\n }\n },\n convertExpiryToUnit (unit, amount) {\n // Note: we want seconds and not milliseconds\n switch (unit) {\n case 'minutes': return (1000 * amount) / DateUtils.MINUTE\n case 'hours': return (1000 * amount) / DateUtils.HOUR\n case 'days': return (1000 * amount) / DateUtils.DAY\n }\n },\n convertExpiryFromUnit (unit, amount) {\n // Note: we want seconds and not milliseconds\n switch (unit) {\n case 'minutes': return 0.001 * amount * DateUtils.MINUTE\n case 'hours': return 0.001 * amount * DateUtils.HOUR\n case 'days': return 0.001 * amount * DateUtils.DAY\n }\n },\n expiryAmountChange () {\n this.expiryAmount =\n Math.max(this.minExpirationInCurrentUnit, this.expiryAmount)\n this.expiryAmount =\n Math.min(this.maxExpirationInCurrentUnit, this.expiryAmount)\n this.updatePollToParent()\n },\n updatePollToParent () {\n const expiresIn = this.convertExpiryFromUnit(\n this.expiryUnit,\n this.expiryAmount\n )\n\n const options = uniq(this.options.filter(option => option !== ''))\n if (options.length < 2) {\n this.$emit('update-poll', { error: this.$t('polls.not_enough_options') })\n return\n }\n this.$emit('update-poll', {\n options,\n multiple: this.pollType === 'multiple',\n expiresIn\n })\n }\n }\n}\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./poll_form.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./poll_form.js\"\nimport __vue_script__ from \"!!babel-loader!./poll_form.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-1f896331\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./poll_form.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (_vm.visible)?_c('div',{staticClass:\"poll-form\"},[_vm._l((_vm.options),function(option,index){return _c('div',{key:index,staticClass:\"poll-option\"},[_c('div',{staticClass:\"input-container\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.options[index]),expression:\"options[index]\"}],staticClass:\"poll-option-input\",attrs:{\"id\":(\"poll-\" + index),\"type\":\"text\",\"placeholder\":_vm.$t('polls.option'),\"maxlength\":_vm.maxLength},domProps:{\"value\":(_vm.options[index])},on:{\"change\":_vm.updatePollToParent,\"keydown\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\")){ return null; }$event.stopPropagation();$event.preventDefault();return _vm.nextOption(index)},\"input\":function($event){if($event.target.composing){ return; }_vm.$set(_vm.options, index, $event.target.value)}}})]),_vm._v(\" \"),(_vm.options.length > 2)?_c('div',{staticClass:\"icon-container\"},[_c('i',{staticClass:\"icon-cancel\",on:{\"click\":function($event){return _vm.deleteOption(index)}}})]):_vm._e()])}),_vm._v(\" \"),(_vm.options.length < _vm.maxOptions)?_c('a',{staticClass:\"add-option faint\",on:{\"click\":_vm.addOption}},[_c('i',{staticClass:\"icon-plus\"}),_vm._v(\"\\n \"+_vm._s(_vm.$t(\"polls.add_option\"))+\"\\n \")]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"poll-type-expiry\"},[_c('div',{staticClass:\"poll-type\",attrs:{\"title\":_vm.$t('polls.type')}},[_c('label',{staticClass:\"select\",attrs:{\"for\":\"poll-type-selector\"}},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.pollType),expression:\"pollType\"}],staticClass:\"select\",on:{\"change\":[function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.pollType=$event.target.multiple ? $$selectedVal : $$selectedVal[0]},_vm.updatePollToParent]}},[_c('option',{attrs:{\"value\":\"single\"}},[_vm._v(_vm._s(_vm.$t('polls.single_choice')))]),_vm._v(\" \"),_c('option',{attrs:{\"value\":\"multiple\"}},[_vm._v(_vm._s(_vm.$t('polls.multiple_choices')))])]),_vm._v(\" \"),_c('i',{staticClass:\"icon-down-open\"})])]),_vm._v(\" \"),_c('div',{staticClass:\"poll-expiry\",attrs:{\"title\":_vm.$t('polls.expiry')}},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.expiryAmount),expression:\"expiryAmount\"}],staticClass:\"expiry-amount hide-number-spinner\",attrs:{\"type\":\"number\",\"min\":_vm.minExpirationInCurrentUnit,\"max\":_vm.maxExpirationInCurrentUnit},domProps:{\"value\":(_vm.expiryAmount)},on:{\"change\":_vm.expiryAmountChange,\"input\":function($event){if($event.target.composing){ return; }_vm.expiryAmount=$event.target.value}}}),_vm._v(\" \"),_c('label',{staticClass:\"expiry-unit select\"},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.expiryUnit),expression:\"expiryUnit\"}],on:{\"change\":[function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.expiryUnit=$event.target.multiple ? $$selectedVal : $$selectedVal[0]},_vm.expiryAmountChange]}},_vm._l((_vm.expiryUnits),function(unit){return _c('option',{key:unit,domProps:{\"value\":unit}},[_vm._v(\"\\n \"+_vm._s(_vm.$t((\"time.\" + unit + \"_short\"), ['']))+\"\\n \")])}),0),_vm._v(\" \"),_c('i',{staticClass:\"icon-down-open\"})])])])],2):_vm._e()}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import statusPoster from '../../services/status_poster/status_poster.service.js'\nimport MediaUpload from '../media_upload/media_upload.vue'\nimport ScopeSelector from '../scope_selector/scope_selector.vue'\nimport EmojiInput from '../emoji_input/emoji_input.vue'\nimport PollForm from '../poll/poll_form.vue'\nimport fileTypeService from '../../services/file_type/file_type.service.js'\nimport { findOffset } from '../../services/offset_finder/offset_finder.service.js'\nimport { reject, map, uniqBy } from 'lodash'\nimport suggestor from '../emoji_input/suggestor.js'\nimport { mapGetters } from 'vuex'\nimport Checkbox from '../checkbox/checkbox.vue'\n\nconst buildMentionsString = ({ user, attentions = [] }, currentUser) => {\n let allAttentions = [...attentions]\n\n allAttentions.unshift(user)\n\n allAttentions = uniqBy(allAttentions, 'id')\n allAttentions = reject(allAttentions, { id: currentUser.id })\n\n let mentions = map(allAttentions, (attention) => {\n return `@${attention.screen_name}`\n })\n\n return mentions.length > 0 ? mentions.join(' ') + ' ' : ''\n}\n\nconst PostStatusForm = {\n props: [\n 'replyTo',\n 'repliedUser',\n 'attentions',\n 'copyMessageScope',\n 'subject'\n ],\n components: {\n MediaUpload,\n EmojiInput,\n PollForm,\n ScopeSelector,\n Checkbox\n },\n mounted () {\n this.resize(this.$refs.textarea)\n const textLength = this.$refs.textarea.value.length\n this.$refs.textarea.setSelectionRange(textLength, textLength)\n\n if (this.replyTo) {\n this.$refs.textarea.focus()\n }\n },\n data () {\n const preset = this.$route.query.message\n let statusText = preset || ''\n\n const { scopeCopy } = this.$store.getters.mergedConfig\n\n if (this.replyTo) {\n const currentUser = this.$store.state.users.currentUser\n statusText = buildMentionsString({ user: this.repliedUser, attentions: this.attentions }, currentUser)\n }\n\n const scope = ((this.copyMessageScope && scopeCopy) || this.copyMessageScope === 'direct')\n ? this.copyMessageScope\n : this.$store.state.users.currentUser.default_scope\n\n const { postContentType: contentType } = this.$store.getters.mergedConfig\n\n return {\n dropFiles: [],\n submitDisabled: false,\n error: null,\n posting: false,\n highlighted: 0,\n newStatus: {\n spoilerText: this.subject || '',\n status: statusText,\n nsfw: false,\n files: [],\n poll: {},\n visibility: scope,\n contentType\n },\n caret: 0,\n pollFormVisible: false\n }\n },\n computed: {\n users () {\n return this.$store.state.users.users\n },\n userDefaultScope () {\n return this.$store.state.users.currentUser.default_scope\n },\n showAllScopes () {\n return !this.mergedConfig.minimalScopesMode\n },\n emojiUserSuggestor () {\n return suggestor({\n emoji: [\n ...this.$store.state.instance.emoji,\n ...this.$store.state.instance.customEmoji\n ],\n users: this.$store.state.users.users,\n updateUsersList: (input) => this.$store.dispatch('searchUsers', input)\n })\n },\n emojiSuggestor () {\n return suggestor({\n emoji: [\n ...this.$store.state.instance.emoji,\n ...this.$store.state.instance.customEmoji\n ]\n })\n },\n emoji () {\n return this.$store.state.instance.emoji || []\n },\n customEmoji () {\n return this.$store.state.instance.customEmoji || []\n },\n statusLength () {\n return this.newStatus.status.length\n },\n spoilerTextLength () {\n return this.newStatus.spoilerText.length\n },\n statusLengthLimit () {\n return this.$store.state.instance.textlimit\n },\n hasStatusLengthLimit () {\n return this.statusLengthLimit > 0\n },\n charactersLeft () {\n return this.statusLengthLimit - (this.statusLength + this.spoilerTextLength)\n },\n isOverLengthLimit () {\n return this.hasStatusLengthLimit && (this.charactersLeft < 0)\n },\n minimalScopesMode () {\n return this.$store.state.instance.minimalScopesMode\n },\n alwaysShowSubject () {\n return this.mergedConfig.alwaysShowSubjectInput\n },\n postFormats () {\n return this.$store.state.instance.postFormats || []\n },\n safeDMEnabled () {\n return this.$store.state.instance.safeDM\n },\n pollsAvailable () {\n return this.$store.state.instance.pollsAvailable &&\n this.$store.state.instance.pollLimits.max_options >= 2\n },\n hideScopeNotice () {\n return this.$store.getters.mergedConfig.hideScopeNotice\n },\n pollContentError () {\n return this.pollFormVisible &&\n this.newStatus.poll &&\n this.newStatus.poll.error\n },\n ...mapGetters(['mergedConfig'])\n },\n methods: {\n postStatus (newStatus) {\n if (this.posting) { return }\n if (this.submitDisabled) { return }\n\n if (this.newStatus.status === '') {\n if (this.newStatus.files.length === 0) {\n this.error = 'Cannot post an empty status with no files'\n return\n }\n }\n\n const poll = this.pollFormVisible ? this.newStatus.poll : {}\n if (this.pollContentError) {\n this.error = this.pollContentError\n return\n }\n\n this.posting = true\n statusPoster.postStatus({\n status: newStatus.status,\n spoilerText: newStatus.spoilerText || null,\n visibility: newStatus.visibility,\n sensitive: newStatus.nsfw,\n media: newStatus.files,\n store: this.$store,\n inReplyToStatusId: this.replyTo,\n contentType: newStatus.contentType,\n poll\n }).then((data) => {\n if (!data.error) {\n this.newStatus = {\n status: '',\n spoilerText: '',\n files: [],\n visibility: newStatus.visibility,\n contentType: newStatus.contentType,\n poll: {}\n }\n this.pollFormVisible = false\n this.$refs.mediaUpload.clearFile()\n this.clearPollForm()\n this.$emit('posted')\n let el = this.$el.querySelector('textarea')\n el.style.height = 'auto'\n el.style.height = undefined\n this.error = null\n } else {\n this.error = data.error\n }\n this.posting = false\n })\n },\n addMediaFile (fileInfo) {\n this.newStatus.files.push(fileInfo)\n this.enableSubmit()\n },\n removeMediaFile (fileInfo) {\n let index = this.newStatus.files.indexOf(fileInfo)\n this.newStatus.files.splice(index, 1)\n },\n uploadFailed (errString, templateArgs) {\n templateArgs = templateArgs || {}\n this.error = this.$t('upload.error.base') + ' ' + this.$t('upload.error.' + errString, templateArgs)\n this.enableSubmit()\n },\n disableSubmit () {\n this.submitDisabled = true\n },\n enableSubmit () {\n this.submitDisabled = false\n },\n type (fileInfo) {\n return fileTypeService.fileType(fileInfo.mimetype)\n },\n paste (e) {\n this.resize(e)\n if (e.clipboardData.files.length > 0) {\n // prevent pasting of file as text\n e.preventDefault()\n // Strangely, files property gets emptied after event propagation\n // Trying to wrap it in array doesn't work. Plus I doubt it's possible\n // to hold more than one file in clipboard.\n this.dropFiles = [e.clipboardData.files[0]]\n }\n },\n fileDrop (e) {\n if (e.dataTransfer.files.length > 0) {\n e.preventDefault() // allow dropping text like before\n this.dropFiles = e.dataTransfer.files\n }\n },\n fileDrag (e) {\n e.dataTransfer.dropEffect = 'copy'\n },\n onEmojiInputInput (e) {\n this.$nextTick(() => {\n this.resize(this.$refs['textarea'])\n })\n },\n resize (e) {\n const target = e.target || e\n if (!(target instanceof window.Element)) { return }\n\n // Reset to default height for empty form, nothing else to do here.\n if (target.value === '') {\n target.style.height = null\n this.$refs['emoji-input'].resize()\n return\n }\n\n const formRef = this.$refs['form']\n const bottomRef = this.$refs['bottom']\n /* Scroller is either `window` (replies in TL), sidebar (main post form,\n * replies in notifs) or mobile post form. Note that getting and setting\n * scroll is different for `Window` and `Element`s\n */\n const bottomBottomPaddingStr = window.getComputedStyle(bottomRef)['padding-bottom']\n const bottomBottomPadding = Number(bottomBottomPaddingStr.substring(0, bottomBottomPaddingStr.length - 2))\n\n const scrollerRef = this.$el.closest('.sidebar-scroller') ||\n this.$el.closest('.post-form-modal-view') ||\n window\n\n // Getting info about padding we have to account for, removing 'px' part\n const topPaddingStr = window.getComputedStyle(target)['padding-top']\n const bottomPaddingStr = window.getComputedStyle(target)['padding-bottom']\n const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2))\n const bottomPadding = Number(bottomPaddingStr.substring(0, bottomPaddingStr.length - 2))\n const vertPadding = topPadding + bottomPadding\n\n /* Explanation:\n *\n * https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight\n * scrollHeight returns element's scrollable content height, i.e. visible\n * element + overscrolled parts of it. We use it to determine when text\n * inside the textarea exceeded its height, so we can set height to prevent\n * overscroll, i.e. make textarea grow with the text. HOWEVER, since we\n * explicitly set new height, scrollHeight won't go below that, so we can't\n * SHRINK the textarea when there's extra space. To workaround that we set\n * height to 'auto' which makes textarea tiny again, so that scrollHeight\n * will match text height again. HOWEVER, shrinking textarea can screw with\n * the scroll since there might be not enough padding around form-bottom to even\n * warrant a scroll, so it will jump to 0 and refuse to move anywhere,\n * so we check current scroll position before shrinking and then restore it\n * with needed delta.\n */\n\n // this part has to be BEFORE the content size update\n const currentScroll = scrollerRef === window\n ? scrollerRef.scrollY\n : scrollerRef.scrollTop\n const scrollerHeight = scrollerRef === window\n ? scrollerRef.innerHeight\n : scrollerRef.offsetHeight\n const scrollerBottomBorder = currentScroll + scrollerHeight\n\n // BEGIN content size update\n target.style.height = 'auto'\n const newHeight = target.scrollHeight - vertPadding\n target.style.height = `${newHeight}px`\n // END content size update\n\n // We check where the bottom border of form-bottom element is, this uses findOffset\n // to find offset relative to scrollable container (scroller)\n const bottomBottomBorder = bottomRef.offsetHeight + findOffset(bottomRef, scrollerRef).top + bottomBottomPadding\n\n const isBottomObstructed = scrollerBottomBorder < bottomBottomBorder\n const isFormBiggerThanScroller = scrollerHeight < formRef.offsetHeight\n const bottomChangeDelta = bottomBottomBorder - scrollerBottomBorder\n // The intention is basically this;\n // Keep form-bottom always visible so that submit button is in view EXCEPT\n // if form element bigger than scroller and caret isn't at the end, so that\n // if you scroll up and edit middle of text you won't get scrolled back to bottom\n const shouldScrollToBottom = isBottomObstructed &&\n !(isFormBiggerThanScroller &&\n this.$refs.textarea.selectionStart !== this.$refs.textarea.value.length)\n const totalDelta = shouldScrollToBottom ? bottomChangeDelta : 0\n const targetScroll = currentScroll + totalDelta\n\n if (scrollerRef === window) {\n scrollerRef.scroll(0, targetScroll)\n } else {\n scrollerRef.scrollTop = targetScroll\n }\n\n this.$refs['emoji-input'].resize()\n },\n showEmojiPicker () {\n this.$refs['textarea'].focus()\n this.$refs['emoji-input'].triggerShowPicker()\n },\n clearError () {\n this.error = null\n },\n changeVis (visibility) {\n this.newStatus.visibility = visibility\n },\n togglePollForm () {\n this.pollFormVisible = !this.pollFormVisible\n },\n setPoll (poll) {\n this.newStatus.poll = poll\n },\n clearPollForm () {\n if (this.$refs.pollForm) {\n this.$refs.pollForm.clear()\n }\n },\n dismissScopeNotice () {\n this.$store.dispatch('setOption', { name: 'hideScopeNotice', value: true })\n }\n }\n}\n\nexport default PostStatusForm\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./post_status_form.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./post_status_form.js\"\nimport __vue_script__ from \"!!babel-loader!./post_status_form.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-c2ba770c\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./post_status_form.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:\"form\",staticClass:\"post-status-form\"},[_c('form',{attrs:{\"autocomplete\":\"off\"},on:{\"submit\":function($event){$event.preventDefault();return _vm.postStatus(_vm.newStatus)}}},[_c('div',{staticClass:\"form-group\"},[(!_vm.$store.state.users.currentUser.locked && _vm.newStatus.visibility == 'private')?_c('i18n',{staticClass:\"visibility-notice\",attrs:{\"path\":\"post_status.account_not_locked_warning\",\"tag\":\"p\"}},[_c('router-link',{attrs:{\"to\":{ name: 'user-settings' }}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('post_status.account_not_locked_warning_link'))+\"\\n \")])],1):_vm._e(),_vm._v(\" \"),(!_vm.hideScopeNotice && _vm.newStatus.visibility === 'public')?_c('p',{staticClass:\"visibility-notice notice-dismissible\"},[_c('span',[_vm._v(_vm._s(_vm.$t('post_status.scope_notice.public')))]),_vm._v(\" \"),_c('a',{staticClass:\"button-icon dismiss\",on:{\"click\":function($event){$event.preventDefault();return _vm.dismissScopeNotice()}}},[_c('i',{staticClass:\"icon-cancel\"})])]):(!_vm.hideScopeNotice && _vm.newStatus.visibility === 'unlisted')?_c('p',{staticClass:\"visibility-notice notice-dismissible\"},[_c('span',[_vm._v(_vm._s(_vm.$t('post_status.scope_notice.unlisted')))]),_vm._v(\" \"),_c('a',{staticClass:\"button-icon dismiss\",on:{\"click\":function($event){$event.preventDefault();return _vm.dismissScopeNotice()}}},[_c('i',{staticClass:\"icon-cancel\"})])]):(!_vm.hideScopeNotice && _vm.newStatus.visibility === 'private' && _vm.$store.state.users.currentUser.locked)?_c('p',{staticClass:\"visibility-notice notice-dismissible\"},[_c('span',[_vm._v(_vm._s(_vm.$t('post_status.scope_notice.private')))]),_vm._v(\" \"),_c('a',{staticClass:\"button-icon dismiss\",on:{\"click\":function($event){$event.preventDefault();return _vm.dismissScopeNotice()}}},[_c('i',{staticClass:\"icon-cancel\"})])]):(_vm.newStatus.visibility === 'direct')?_c('p',{staticClass:\"visibility-notice\"},[(_vm.safeDMEnabled)?_c('span',[_vm._v(_vm._s(_vm.$t('post_status.direct_warning_to_first_only')))]):_c('span',[_vm._v(_vm._s(_vm.$t('post_status.direct_warning_to_all')))])]):_vm._e(),_vm._v(\" \"),(_vm.newStatus.spoilerText || _vm.alwaysShowSubject)?_c('EmojiInput',{staticClass:\"form-control\",attrs:{\"enable-emoji-picker\":\"\",\"suggest\":_vm.emojiSuggestor},model:{value:(_vm.newStatus.spoilerText),callback:function ($$v) {_vm.$set(_vm.newStatus, \"spoilerText\", $$v)},expression:\"newStatus.spoilerText\"}},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newStatus.spoilerText),expression:\"newStatus.spoilerText\"}],staticClass:\"form-post-subject\",attrs:{\"type\":\"text\",\"placeholder\":_vm.$t('post_status.content_warning')},domProps:{\"value\":(_vm.newStatus.spoilerText)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.$set(_vm.newStatus, \"spoilerText\", $event.target.value)}}})]):_vm._e(),_vm._v(\" \"),_c('EmojiInput',{ref:\"emoji-input\",staticClass:\"form-control main-input\",attrs:{\"suggest\":_vm.emojiUserSuggestor,\"enable-emoji-picker\":\"\",\"hide-emoji-button\":\"\",\"enable-sticker-picker\":\"\"},on:{\"input\":_vm.onEmojiInputInput,\"sticker-uploaded\":_vm.addMediaFile,\"sticker-upload-failed\":_vm.uploadFailed},model:{value:(_vm.newStatus.status),callback:function ($$v) {_vm.$set(_vm.newStatus, \"status\", $$v)},expression:\"newStatus.status\"}},[_c('textarea',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newStatus.status),expression:\"newStatus.status\"}],ref:\"textarea\",staticClass:\"form-post-body\",attrs:{\"placeholder\":_vm.$t('post_status.default'),\"rows\":\"1\",\"disabled\":_vm.posting},domProps:{\"value\":(_vm.newStatus.status)},on:{\"keydown\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\")){ return null; }if(!$event.metaKey){ return null; }return _vm.postStatus(_vm.newStatus)},\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\")){ return null; }if(!$event.ctrlKey){ return null; }return _vm.postStatus(_vm.newStatus)},\"drop\":_vm.fileDrop,\"dragover\":function($event){$event.preventDefault();return _vm.fileDrag($event)},\"input\":[function($event){if($event.target.composing){ return; }_vm.$set(_vm.newStatus, \"status\", $event.target.value)},_vm.resize],\"compositionupdate\":_vm.resize,\"paste\":_vm.paste}}),_vm._v(\" \"),(_vm.hasStatusLengthLimit)?_c('p',{staticClass:\"character-counter faint\",class:{ error: _vm.isOverLengthLimit }},[_vm._v(\"\\n \"+_vm._s(_vm.charactersLeft)+\"\\n \")]):_vm._e()]),_vm._v(\" \"),_c('div',{staticClass:\"visibility-tray\"},[_c('scope-selector',{attrs:{\"show-all\":_vm.showAllScopes,\"user-default\":_vm.userDefaultScope,\"original-scope\":_vm.copyMessageScope,\"initial-scope\":_vm.newStatus.visibility,\"on-scope-change\":_vm.changeVis}}),_vm._v(\" \"),(_vm.postFormats.length > 1)?_c('div',{staticClass:\"text-format\"},[_c('label',{staticClass:\"select\",attrs:{\"for\":\"post-content-type\"}},[_c('select',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.newStatus.contentType),expression:\"newStatus.contentType\"}],staticClass:\"form-control\",attrs:{\"id\":\"post-content-type\"},on:{\"change\":function($event){var $$selectedVal = Array.prototype.filter.call($event.target.options,function(o){return o.selected}).map(function(o){var val = \"_value\" in o ? o._value : o.value;return val}); _vm.$set(_vm.newStatus, \"contentType\", $event.target.multiple ? $$selectedVal : $$selectedVal[0])}}},_vm._l((_vm.postFormats),function(postFormat){return _c('option',{key:postFormat,domProps:{\"value\":postFormat}},[_vm._v(\"\\n \"+_vm._s(_vm.$t((\"post_status.content_type[\\\"\" + postFormat + \"\\\"]\")))+\"\\n \")])}),0),_vm._v(\" \"),_c('i',{staticClass:\"icon-down-open\"})])]):_vm._e(),_vm._v(\" \"),(_vm.postFormats.length === 1 && _vm.postFormats[0] !== 'text/plain')?_c('div',{staticClass:\"text-format\"},[_c('span',{staticClass:\"only-format\"},[_vm._v(\"\\n \"+_vm._s(_vm.$t((\"post_status.content_type[\\\"\" + (_vm.postFormats[0]) + \"\\\"]\")))+\"\\n \")])]):_vm._e()],1)],1),_vm._v(\" \"),(_vm.pollsAvailable)?_c('poll-form',{ref:\"pollForm\",attrs:{\"visible\":_vm.pollFormVisible},on:{\"update-poll\":_vm.setPoll}}):_vm._e(),_vm._v(\" \"),_c('div',{ref:\"bottom\",staticClass:\"form-bottom\"},[_c('div',{staticClass:\"form-bottom-left\"},[_c('media-upload',{ref:\"mediaUpload\",staticClass:\"media-upload-icon\",attrs:{\"drop-files\":_vm.dropFiles},on:{\"uploading\":_vm.disableSubmit,\"uploaded\":_vm.addMediaFile,\"upload-failed\":_vm.uploadFailed}}),_vm._v(\" \"),_c('div',{staticClass:\"emoji-icon\"},[_c('i',{staticClass:\"icon-smile btn btn-default\",attrs:{\"title\":_vm.$t('emoji.add_emoji')},on:{\"click\":_vm.showEmojiPicker}})]),_vm._v(\" \"),(_vm.pollsAvailable)?_c('div',{staticClass:\"poll-icon\",class:{ selected: _vm.pollFormVisible }},[_c('i',{staticClass:\"icon-chart-bar btn btn-default\",attrs:{\"title\":_vm.$t('polls.add_poll')},on:{\"click\":_vm.togglePollForm}})]):_vm._e()],1),_vm._v(\" \"),(_vm.posting)?_c('button',{staticClass:\"btn btn-default\",attrs:{\"disabled\":\"\"}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('post_status.posting'))+\"\\n \")]):(_vm.isOverLengthLimit)?_c('button',{staticClass:\"btn btn-default\",attrs:{\"disabled\":\"\"}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('general.submit'))+\"\\n \")]):_c('button',{staticClass:\"btn btn-default\",attrs:{\"disabled\":_vm.submitDisabled,\"type\":\"submit\"}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('general.submit'))+\"\\n \")])]),_vm._v(\" \"),(_vm.error)?_c('div',{staticClass:\"alert error\"},[_vm._v(\"\\n Error: \"+_vm._s(_vm.error)+\"\\n \"),_c('i',{staticClass:\"button-icon icon-cancel\",on:{\"click\":_vm.clearError}})]):_vm._e(),_vm._v(\" \"),_c('div',{staticClass:\"attachments\"},_vm._l((_vm.newStatus.files),function(file){return _c('div',{key:file.url,staticClass:\"media-upload-wrapper\"},[_c('i',{staticClass:\"fa button-icon icon-cancel\",on:{\"click\":function($event){return _vm.removeMediaFile(file)}}}),_vm._v(\" \"),_c('div',{staticClass:\"media-upload-container attachment\"},[(_vm.type(file) === 'image')?_c('img',{staticClass:\"thumbnail media-upload\",attrs:{\"src\":file.url}}):_vm._e(),_vm._v(\" \"),(_vm.type(file) === 'video')?_c('video',{attrs:{\"src\":file.url,\"controls\":\"\"}}):_vm._e(),_vm._v(\" \"),(_vm.type(file) === 'audio')?_c('audio',{attrs:{\"src\":file.url,\"controls\":\"\"}}):_vm._e(),_vm._v(\" \"),(_vm.type(file) === 'unknown')?_c('a',{attrs:{\"href\":file.url}},[_vm._v(_vm._s(file.url))]):_vm._e()])])}),0),_vm._v(\" \"),(_vm.newStatus.files.length > 0)?_c('div',{staticClass:\"upload_settings\"},[_c('Checkbox',{model:{value:(_vm.newStatus.nsfw),callback:function ($$v) {_vm.$set(_vm.newStatus, \"nsfw\", $$v)},expression:\"newStatus.nsfw\"}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('post_status.attachments_sensitive'))+\"\\n \")])],1):_vm._e()],1)])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","const StillImage = {\n props: [\n 'src',\n 'referrerpolicy',\n 'mimetype',\n 'imageLoadError',\n 'imageLoadHandler'\n ],\n data () {\n return {\n stopGifs: this.$store.getters.mergedConfig.stopGifs\n }\n },\n computed: {\n animated () {\n return this.stopGifs && (this.mimetype === 'image/gif' || this.src.endsWith('.gif'))\n }\n },\n methods: {\n onLoad () {\n this.imageLoadHandler && this.imageLoadHandler(this.$refs.src)\n const canvas = this.$refs.canvas\n if (!canvas) return\n const width = this.$refs.src.naturalWidth\n const height = this.$refs.src.naturalHeight\n canvas.width = width\n canvas.height = height\n canvas.getContext('2d').drawImage(this.$refs.src, 0, 0, width, height)\n },\n onError () {\n this.imageLoadError && this.imageLoadError()\n }\n }\n}\n\nexport default StillImage\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!../../../node_modules/vue-loader/lib/selector?type=styles&index=0!./still-image.vue\")\n}\n/* script */\nexport * from \"!!babel-loader!./still-image.js\"\nimport __vue_script__ from \"!!babel-loader!./still-image.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-1bc509fc\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./still-image.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"still-image\",class:{ animated: _vm.animated }},[(_vm.animated)?_c('canvas',{ref:\"canvas\"}):_vm._e(),_vm._v(\" \"),_c('img',{key:_vm.src,ref:\"src\",attrs:{\"src\":_vm.src,\"referrerpolicy\":_vm.referrerpolicy},on:{\"load\":_vm.onLoad,\"error\":_vm.onError}})])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","\n\n\n","/* script */\nexport * from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./timeago.vue\"\nimport __vue_script__ from \"!!babel-loader!../../../node_modules/vue-loader/lib/selector?type=script&index=0!./timeago.vue\"\n/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-ac499830\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./timeago.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = null\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('time',{attrs:{\"datetime\":_vm.time,\"title\":_vm.localeDateString}},[_vm._v(\"\\n \"+_vm._s(_vm.$t(_vm.relativeTime.key, [_vm.relativeTime.num]))+\"\\n\")])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","const fileSizeFormat = (num) => {\n var exponent\n var unit\n var units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']\n if (num < 1) {\n return num + ' ' + units[0]\n }\n\n exponent = Math.min(Math.floor(Math.log(num) / Math.log(1024)), units.length - 1)\n num = (num / Math.pow(1024, exponent)).toFixed(2) * 1\n unit = units[exponent]\n return { num: num, unit: unit }\n}\nconst fileSizeFormatService = {\n fileSizeFormat\n}\nexport default fileSizeFormatService\n","import { debounce } from 'lodash'\n/**\n * suggest - generates a suggestor function to be used by emoji-input\n * data: object providing source information for specific types of suggestions:\n * data.emoji - optional, an array of all emoji available i.e.\n * (state.instance.emoji + state.instance.customEmoji)\n * data.users - optional, an array of all known users\n * updateUsersList - optional, a function to search and append to users\n *\n * Depending on data present one or both (or none) can be present, so if field\n * doesn't support user linking you can just provide only emoji.\n */\n\nconst debounceUserSearch = debounce((data, input) => {\n data.updateUsersList(input)\n}, 500, { leading: true, trailing: false })\n\nexport default data => input => {\n const firstChar = input[0]\n if (firstChar === ':' && data.emoji) {\n return suggestEmoji(data.emoji)(input)\n }\n if (firstChar === '@' && data.users) {\n return suggestUsers(data)(input)\n }\n return []\n}\n\nexport const suggestEmoji = emojis => input => {\n const noPrefix = input.toLowerCase().substr(1)\n return emojis\n .filter(({ displayText }) => displayText.toLowerCase().match(noPrefix))\n .sort((a, b) => {\n let aScore = 0\n let bScore = 0\n\n // An exact match always wins\n aScore += a.displayText.toLowerCase() === noPrefix ? 200 : 0\n bScore += b.displayText.toLowerCase() === noPrefix ? 200 : 0\n\n // Prioritize custom emoji a lot\n aScore += a.imageUrl ? 100 : 0\n bScore += b.imageUrl ? 100 : 0\n\n // Prioritize prefix matches somewhat\n aScore += a.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0\n bScore += b.displayText.toLowerCase().startsWith(noPrefix) ? 10 : 0\n\n // Sort by length\n aScore -= a.displayText.length\n bScore -= b.displayText.length\n\n // Break ties alphabetically\n const alphabetically = a.displayText > b.displayText ? 0.5 : -0.5\n\n return bScore - aScore + alphabetically\n })\n}\n\nexport const suggestUsers = data => input => {\n const noPrefix = input.toLowerCase().substr(1)\n const users = data.users\n\n const newUsers = users.filter(\n user =>\n user.screen_name.toLowerCase().startsWith(noPrefix) ||\n user.name.toLowerCase().startsWith(noPrefix)\n\n /* taking only 20 results so that sorting is a bit cheaper, we display\n * only 5 anyway. could be inaccurate, but we ideally we should query\n * backend anyway\n */\n ).slice(0, 20).sort((a, b) => {\n let aScore = 0\n let bScore = 0\n\n // Matches on screen name (i.e. user@instance) makes a priority\n aScore += a.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0\n bScore += b.screen_name.toLowerCase().startsWith(noPrefix) ? 2 : 0\n\n // Matches on name takes second priority\n aScore += a.name.toLowerCase().startsWith(noPrefix) ? 1 : 0\n bScore += b.name.toLowerCase().startsWith(noPrefix) ? 1 : 0\n\n const diff = (bScore - aScore) * 10\n\n // Then sort alphabetically\n const nameAlphabetically = a.name > b.name ? 1 : -1\n const screenNameAlphabetically = a.screen_name > b.screen_name ? 1 : -1\n\n return diff + nameAlphabetically + screenNameAlphabetically\n /* eslint-disable camelcase */\n }).map(({ screen_name, name, profile_image_url_original }) => ({\n displayText: screen_name,\n detailText: name,\n imageUrl: profile_image_url_original,\n replacement: '@' + screen_name + ' '\n }))\n\n // BE search users if there are no matches\n if (newUsers.length === 0 && data.updateUsersList) {\n debounceUserSearch(data, noPrefix)\n }\n return newUsers\n /* eslint-enable camelcase */\n}\n","import { map } from 'lodash'\nimport apiService from '../api/api.service.js'\n\nconst postStatus = ({ store, status, spoilerText, visibility, sensitive, poll, media = [], inReplyToStatusId = undefined, contentType = 'text/plain' }) => {\n const mediaIds = map(media, 'id')\n\n return apiService.postStatus({\n credentials: store.state.users.currentUser.credentials,\n status,\n spoilerText,\n visibility,\n sensitive,\n mediaIds,\n inReplyToStatusId,\n contentType,\n poll })\n .then((data) => {\n if (!data.error) {\n store.dispatch('addNewStatuses', {\n statuses: [data],\n timeline: 'friends',\n showImmediately: true,\n noIdUpdate: true // To prevent missing notices on next pull.\n })\n }\n return data\n })\n .catch((err) => {\n return {\n error: err.message\n }\n })\n}\n\nconst uploadMedia = ({ store, formData }) => {\n const credentials = store.state.users.currentUser.credentials\n\n return apiService.uploadMedia({ credentials, formData })\n}\n\nconst statusPosterService = {\n postStatus,\n uploadMedia\n}\n\nexport default statusPosterService\n","export const findOffset = (child, parent, { top = 0, left = 0 } = {}, ignorePadding = true) => {\n const result = {\n top: top + child.offsetTop,\n left: left + child.offsetLeft\n }\n if (!ignorePadding && child !== window) {\n const { topPadding, leftPadding } = findPadding(child)\n result.top += ignorePadding ? 0 : topPadding\n result.left += ignorePadding ? 0 : leftPadding\n }\n\n if (child.offsetParent && (parent === window || parent.contains(child.offsetParent) || parent === child.offsetParent)) {\n return findOffset(child.offsetParent, parent, result, false)\n } else {\n if (parent !== window) {\n const { topPadding, leftPadding } = findPadding(parent)\n result.top += topPadding\n result.left += leftPadding\n }\n return result\n }\n}\n\nconst findPadding = (el) => {\n const topPaddingStr = window.getComputedStyle(el)['padding-top']\n const topPadding = Number(topPaddingStr.substring(0, topPaddingStr.length - 2))\n const leftPaddingStr = window.getComputedStyle(el)['padding-left']\n const leftPadding = Number(leftPaddingStr.substring(0, leftPaddingStr.length - 2))\n\n return { topPadding, leftPadding }\n}\n","import { reduce, find } from 'lodash'\n\nexport const replaceWord = (str, toReplace, replacement) => {\n return str.slice(0, toReplace.start) + replacement + str.slice(toReplace.end)\n}\n\nexport const wordAtPosition = (str, pos) => {\n const words = splitIntoWords(str)\n const wordsWithPosition = addPositionToWords(words)\n\n return find(wordsWithPosition, ({ start, end }) => start <= pos && end > pos)\n}\n\nexport const addPositionToWords = (words) => {\n return reduce(words, (result, word) => {\n const data = {\n word,\n start: 0,\n end: word.length\n }\n\n if (result.length > 0) {\n const previous = result.pop()\n\n data.start += previous.end\n data.end += previous.end\n\n result.push(previous)\n }\n\n result.push(data)\n\n return result\n }, [])\n}\n\nexport const splitIntoWords = (str) => {\n // Split at word boundaries\n const regex = /\\b/\n const triggers = /[@#:]+$/\n\n let split = str.split(regex)\n\n // Add trailing @ and # to the following word.\n const words = reduce(split, (result, word) => {\n if (result.length > 0) {\n let previous = result.pop()\n const matches = previous.match(triggers)\n if (matches) {\n previous = previous.replace(triggers, '')\n word = matches[0] + word\n }\n result.push(previous)\n }\n result.push(word)\n\n return result\n }, [])\n\n return words\n}\n\nconst completion = {\n wordAtPosition,\n addPositionToWords,\n splitIntoWords,\n replaceWord\n}\n\nexport default completion\n","import Checkbox from '../checkbox/checkbox.vue'\n\n// At widest, approximately 20 emoji are visible in a row,\n// loading 3 rows, could be overkill for narrow picker\nconst LOAD_EMOJI_BY = 60\n\n// When to start loading new batch emoji, in pixels\nconst LOAD_EMOJI_MARGIN = 64\n\nconst filterByKeyword = (list, keyword = '') => {\n return list.filter(x => x.displayText.includes(keyword))\n}\n\nconst EmojiPicker = {\n props: {\n enableStickerPicker: {\n required: false,\n type: Boolean,\n default: false\n }\n },\n data () {\n return {\n keyword: '',\n activeGroup: 'custom',\n showingStickers: false,\n groupsScrolledClass: 'scrolled-top',\n keepOpen: false,\n customEmojiBufferSlice: LOAD_EMOJI_BY,\n customEmojiTimeout: null,\n customEmojiLoadAllConfirmed: false\n }\n },\n components: {\n StickerPicker: () => import('../sticker_picker/sticker_picker.vue'),\n Checkbox\n },\n methods: {\n onStickerUploaded (e) {\n this.$emit('sticker-uploaded', e)\n },\n onStickerUploadFailed (e) {\n this.$emit('sticker-upload-failed', e)\n },\n onEmoji (emoji) {\n const value = emoji.imageUrl ? `:${emoji.displayText}:` : emoji.replacement\n this.$emit('emoji', { insertion: value, keepOpen: this.keepOpen })\n },\n onScroll (e) {\n const target = (e && e.target) || this.$refs['emoji-groups']\n this.updateScrolledClass(target)\n this.scrolledGroup(target)\n this.triggerLoadMore(target)\n },\n highlight (key) {\n const ref = this.$refs['group-' + key]\n const top = ref[0].offsetTop\n this.setShowStickers(false)\n this.activeGroup = key\n this.$nextTick(() => {\n this.$refs['emoji-groups'].scrollTop = top + 1\n })\n },\n updateScrolledClass (target) {\n if (target.scrollTop <= 5) {\n this.groupsScrolledClass = 'scrolled-top'\n } else if (target.scrollTop >= target.scrollTopMax - 5) {\n this.groupsScrolledClass = 'scrolled-bottom'\n } else {\n this.groupsScrolledClass = 'scrolled-middle'\n }\n },\n triggerLoadMore (target) {\n const ref = this.$refs['group-end-custom'][0]\n if (!ref) return\n const bottom = ref.offsetTop + ref.offsetHeight\n\n const scrollerBottom = target.scrollTop + target.clientHeight\n const scrollerTop = target.scrollTop\n const scrollerMax = target.scrollHeight\n\n // Loads more emoji when they come into view\n const approachingBottom = bottom - scrollerBottom < LOAD_EMOJI_MARGIN\n // Always load when at the very top in case there's no scroll space yet\n const atTop = scrollerTop < 5\n // Don't load when looking at unicode category or at the very bottom\n const bottomAboveViewport = bottom < scrollerTop || scrollerBottom === scrollerMax\n if (!bottomAboveViewport && (approachingBottom || atTop)) {\n this.loadEmoji()\n }\n },\n scrolledGroup (target) {\n const top = target.scrollTop + 5\n this.$nextTick(() => {\n this.emojisView.forEach(group => {\n const ref = this.$refs['group-' + group.id]\n if (ref[0].offsetTop <= top) {\n this.activeGroup = group.id\n }\n })\n })\n },\n loadEmoji () {\n const allLoaded = this.customEmojiBuffer.length === this.filteredEmoji.length\n\n if (allLoaded) {\n return\n }\n\n this.customEmojiBufferSlice += LOAD_EMOJI_BY\n },\n startEmojiLoad (forceUpdate = false) {\n if (!forceUpdate) {\n this.keyword = ''\n }\n this.$nextTick(() => {\n this.$refs['emoji-groups'].scrollTop = 0\n })\n const bufferSize = this.customEmojiBuffer.length\n const bufferPrefilledAll = bufferSize === this.filteredEmoji.length\n if (bufferPrefilledAll && !forceUpdate) {\n return\n }\n this.customEmojiBufferSlice = LOAD_EMOJI_BY\n },\n toggleStickers () {\n this.showingStickers = !this.showingStickers\n },\n setShowStickers (value) {\n this.showingStickers = value\n }\n },\n watch: {\n keyword () {\n this.customEmojiLoadAllConfirmed = false\n this.onScroll()\n this.startEmojiLoad(true)\n }\n },\n computed: {\n activeGroupView () {\n return this.showingStickers ? '' : this.activeGroup\n },\n stickersAvailable () {\n if (this.$store.state.instance.stickers) {\n return this.$store.state.instance.stickers.length > 0\n }\n return 0\n },\n filteredEmoji () {\n return filterByKeyword(\n this.$store.state.instance.customEmoji || [],\n this.keyword\n )\n },\n customEmojiBuffer () {\n return this.filteredEmoji.slice(0, this.customEmojiBufferSlice)\n },\n emojis () {\n const standardEmojis = this.$store.state.instance.emoji || []\n const customEmojis = this.customEmojiBuffer\n\n return [\n {\n id: 'custom',\n text: this.$t('emoji.custom'),\n icon: 'icon-smile',\n emojis: customEmojis\n },\n {\n id: 'standard',\n text: this.$t('emoji.unicode'),\n icon: 'icon-picture',\n emojis: filterByKeyword(standardEmojis, this.keyword)\n }\n ]\n },\n emojisView () {\n return this.emojis.filter(value => value.emojis.length > 0)\n },\n stickerPickerEnabled () {\n return (this.$store.state.instance.stickers || []).length !== 0\n }\n }\n}\n\nexport default EmojiPicker\n","function injectStyle (context) {\n require(\"!!vue-style-loader!css-loader?minimize!../../../node_modules/vue-loader/lib/style-compiler/index?{\\\"optionsId\\\":\\\"0\\\",\\\"vue\\\":true,\\\"scoped\\\":false,\\\"sourceMap\\\":false}!sass-loader!./emoji_picker.scss\")\n}\n/* script */\nexport * from \"!!babel-loader!./emoji_picker.js\"\nimport __vue_script__ from \"!!babel-loader!./emoji_picker.js\"/* template */\nimport {render as __vue_render__, staticRenderFns as __vue_static_render_fns__} from \"!!../../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-47d21b3b\\\",\\\"hasScoped\\\":false,\\\"optionsId\\\":\\\"0\\\",\\\"buble\\\":{\\\"transforms\\\":{}}}!../../../node_modules/vue-loader/lib/selector?type=template&index=0!./emoji_picker.vue\"\n/* template functional */\nvar __vue_template_functional__ = false\n/* styles */\nvar __vue_styles__ = injectStyle\n/* scopeId */\nvar __vue_scopeId__ = null\n/* moduleIdentifier (server only) */\nvar __vue_module_identifier__ = null\nimport normalizeComponent from \"!../../../node_modules/vue-loader/lib/runtime/component-normalizer\"\nvar Component = normalizeComponent(\n __vue_script__,\n __vue_render__,\n __vue_static_render_fns__,\n __vue_template_functional__,\n __vue_styles__,\n __vue_scopeId__,\n __vue_module_identifier__\n)\n\nexport default Component.exports\n","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"emoji-picker panel panel-default panel-body\"},[_c('div',{staticClass:\"heading\"},[_c('span',{staticClass:\"emoji-tabs\"},_vm._l((_vm.emojis),function(group){return _c('span',{key:group.id,staticClass:\"emoji-tabs-item\",class:{\n active: _vm.activeGroupView === group.id,\n disabled: group.emojis.length === 0\n },attrs:{\"title\":group.text},on:{\"click\":function($event){$event.preventDefault();return _vm.highlight(group.id)}}},[_c('i',{class:group.icon})])}),0),_vm._v(\" \"),(_vm.stickerPickerEnabled)?_c('span',{staticClass:\"additional-tabs\"},[_c('span',{staticClass:\"stickers-tab-icon additional-tabs-item\",class:{active: _vm.showingStickers},attrs:{\"title\":_vm.$t('emoji.stickers')},on:{\"click\":function($event){$event.preventDefault();return _vm.toggleStickers($event)}}},[_c('i',{staticClass:\"icon-star\"})])]):_vm._e()]),_vm._v(\" \"),_c('div',{staticClass:\"content\"},[_c('div',{staticClass:\"emoji-content\",class:{hidden: _vm.showingStickers}},[_c('div',{staticClass:\"emoji-search\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.keyword),expression:\"keyword\"}],staticClass:\"form-control\",attrs:{\"type\":\"text\",\"placeholder\":_vm.$t('emoji.search_emoji')},domProps:{\"value\":(_vm.keyword)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.keyword=$event.target.value}}})]),_vm._v(\" \"),_c('div',{ref:\"emoji-groups\",staticClass:\"emoji-groups\",class:_vm.groupsScrolledClass,on:{\"scroll\":_vm.onScroll}},_vm._l((_vm.emojisView),function(group){return _c('div',{key:group.id,staticClass:\"emoji-group\"},[_c('h6',{ref:'group-' + group.id,refInFor:true,staticClass:\"emoji-group-title\"},[_vm._v(\"\\n \"+_vm._s(group.text)+\"\\n \")]),_vm._v(\" \"),_vm._l((group.emojis),function(emoji){return _c('span',{key:group.id + emoji.displayText,staticClass:\"emoji-item\",attrs:{\"title\":emoji.displayText},on:{\"click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.onEmoji(emoji)}}},[(!emoji.imageUrl)?_c('span',[_vm._v(_vm._s(emoji.replacement))]):_c('img',{attrs:{\"src\":emoji.imageUrl}})])}),_vm._v(\" \"),_c('span',{ref:'group-end-' + group.id,refInFor:true})],2)}),0),_vm._v(\" \"),_c('div',{staticClass:\"keep-open\"},[_c('Checkbox',{model:{value:(_vm.keepOpen),callback:function ($$v) {_vm.keepOpen=$$v},expression:\"keepOpen\"}},[_vm._v(\"\\n \"+_vm._s(_vm.$t('emoji.keep_open'))+\"\\n \")])],1)]),_vm._v(\" \"),(_vm.showingStickers)?_c('div',{staticClass:\"stickers-content\"},[_c('sticker-picker',{on:{\"uploaded\":_vm.onStickerUploaded,\"upload-failed\":_vm.onStickerUploadFailed}})],1):_vm._e()])])}\nvar staticRenderFns = []\nexport { render, staticRenderFns }","import Completion from '../../services/completion/completion.js'\nimport EmojiPicker from '../emoji_picker/emoji_picker.vue'\nimport { take } from 'lodash'\nimport { findOffset } from '../../services/offset_finder/offset_finder.service.js'\n\n/**\n * EmojiInput - augmented inputs for emoji and autocomplete support in inputs\n * without having to give up the comfort of and