@nextcloud/vue 3.10.2 → 4.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/CHANGELOG.md +114 -19
  2. package/README.md +9 -10
  3. package/dist/Components/ActionButton.js +24 -3
  4. package/dist/Components/ActionButton.js.map +1 -1
  5. package/dist/Components/ActionCaption.js +23 -0
  6. package/dist/Components/ActionCaption.js.map +1 -0
  7. package/dist/Components/ActionCheckbox.js +24 -3
  8. package/dist/Components/ActionCheckbox.js.map +1 -1
  9. package/dist/Components/ActionInput.js +124 -21
  10. package/dist/Components/ActionInput.js.map +1 -1
  11. package/dist/Components/ActionLink.js +24 -3
  12. package/dist/Components/ActionLink.js.map +1 -1
  13. package/dist/Components/ActionRadio.js +24 -3
  14. package/dist/Components/ActionRadio.js.map +1 -1
  15. package/dist/Components/ActionRouter.js +23 -2
  16. package/dist/Components/ActionRouter.js.map +1 -1
  17. package/dist/Components/ActionSeparator.js +1 -1
  18. package/dist/Components/ActionSeparator.js.map +1 -1
  19. package/dist/Components/ActionText.js +23 -2
  20. package/dist/Components/ActionText.js.map +1 -1
  21. package/dist/Components/ActionTextEditable.js +45 -3
  22. package/dist/Components/ActionTextEditable.js.map +1 -1
  23. package/dist/Components/Actions.js +25 -4
  24. package/dist/Components/Actions.js.map +1 -1
  25. package/dist/Components/AppContent.js +21 -1
  26. package/dist/Components/AppContent.js.map +1 -1
  27. package/dist/Components/AppContentDetails.js +1 -1
  28. package/dist/Components/AppContentDetails.js.map +1 -1
  29. package/dist/Components/AppContentList.js +1 -1
  30. package/dist/Components/AppContentList.js.map +1 -1
  31. package/dist/Components/AppNavigation.js +109 -2
  32. package/dist/Components/AppNavigation.js.map +1 -1
  33. package/dist/Components/AppNavigationCaption.js +66 -1
  34. package/dist/Components/AppNavigationCaption.js.map +1 -1
  35. package/dist/Components/AppNavigationCounter.js +2 -2
  36. package/dist/Components/AppNavigationCounter.js.map +1 -1
  37. package/dist/Components/AppNavigationIconBullet.js +2 -2
  38. package/dist/Components/AppNavigationIconBullet.js.map +1 -1
  39. package/dist/Components/AppNavigationItem.js +49 -7
  40. package/dist/Components/AppNavigationItem.js.map +1 -1
  41. package/dist/Components/AppNavigationNew.js +1 -1
  42. package/dist/Components/AppNavigationNew.js.map +1 -1
  43. package/dist/Components/AppNavigationNewItem.js +2 -2
  44. package/dist/Components/AppNavigationNewItem.js.map +1 -1
  45. package/dist/Components/AppNavigationSettings.js +5 -5
  46. package/dist/Components/AppNavigationSettings.js.map +1 -1
  47. package/dist/Components/AppNavigationSpacer.js +1 -1
  48. package/dist/Components/AppNavigationSpacer.js.map +1 -1
  49. package/dist/Components/AppNavigationToggle.js +109 -2
  50. package/dist/Components/AppNavigationToggle.js.map +1 -1
  51. package/dist/Components/AppSettingsDialog.js +64 -22
  52. package/dist/Components/AppSettingsDialog.js.map +1 -1
  53. package/dist/Components/AppSettingsSection.js +1 -1
  54. package/dist/Components/AppSettingsSection.js.map +1 -1
  55. package/dist/Components/AppSidebar.js +38 -17
  56. package/dist/Components/AppSidebar.js.map +1 -1
  57. package/dist/Components/AppSidebarTab.js +1 -1
  58. package/dist/Components/AppSidebarTab.js.map +1 -1
  59. package/dist/Components/Avatar.js +9 -10
  60. package/dist/Components/Avatar.js.map +1 -1
  61. package/dist/Components/Breadcrumb.js +33 -12
  62. package/dist/Components/Breadcrumb.js.map +1 -1
  63. package/dist/Components/Breadcrumbs.js +59 -17
  64. package/dist/Components/Breadcrumbs.js.map +1 -1
  65. package/dist/Components/CheckboxRadioSwitch.js +44 -0
  66. package/dist/Components/CheckboxRadioSwitch.js.map +1 -0
  67. package/dist/Components/ColorPicker.js +6 -7
  68. package/dist/Components/ColorPicker.js.map +1 -1
  69. package/dist/Components/Content.js +2 -2
  70. package/dist/Components/Content.js.map +1 -1
  71. package/dist/Components/CounterBubble.js +23 -0
  72. package/dist/Components/CounterBubble.js.map +1 -0
  73. package/dist/Components/DatetimePicker.js +341 -3
  74. package/dist/Components/DatetimePicker.js.map +1 -1
  75. package/dist/Components/EmojiPicker.js +14 -14
  76. package/dist/Components/EmojiPicker.js.map +1 -1
  77. package/dist/Components/EmptyContent.js +2 -2
  78. package/dist/Components/EmptyContent.js.map +1 -1
  79. package/dist/Components/Highlight.js +3 -3
  80. package/dist/Components/Highlight.js.map +1 -1
  81. package/dist/Components/ListItem.js +130 -0
  82. package/dist/Components/ListItem.js.map +1 -0
  83. package/dist/Components/ListItemIcon.js +20 -21
  84. package/dist/Components/ListItemIcon.js.map +1 -1
  85. package/dist/Components/Modal.js +53 -11
  86. package/dist/Components/Modal.js.map +1 -1
  87. package/dist/Components/Multiselect.js +22 -23
  88. package/dist/Components/Multiselect.js.map +1 -1
  89. package/dist/Components/MultiselectTags.js +24 -25
  90. package/dist/Components/MultiselectTags.js.map +1 -1
  91. package/dist/Components/Popover.js +2 -2
  92. package/dist/Components/Popover.js.map +1 -1
  93. package/dist/Components/PopoverMenu.js +1 -1
  94. package/dist/Components/PopoverMenu.js.map +1 -1
  95. package/dist/Components/ProgressBar.js +2 -2
  96. package/dist/Components/ProgressBar.js.map +1 -1
  97. package/dist/Components/RichContenteditable.js +2 -2
  98. package/dist/Components/RichContenteditable.js.map +1 -1
  99. package/dist/Components/SettingsInputText.js +22 -1
  100. package/dist/Components/SettingsInputText.js.map +1 -1
  101. package/dist/Components/SettingsSection.js +2 -2
  102. package/dist/Components/SettingsSection.js.map +1 -1
  103. package/dist/Components/SettingsSelectGroup.js +41 -21
  104. package/dist/Components/SettingsSelectGroup.js.map +1 -1
  105. package/dist/Components/TimezonePicker.js +340 -0
  106. package/dist/Components/TimezonePicker.js.map +1 -0
  107. package/dist/Components/UserBubble.js +35 -36
  108. package/dist/Components/UserBubble.js.map +1 -1
  109. package/dist/Directives/Focus.js +1 -1
  110. package/dist/Directives/Focus.js.map +1 -1
  111. package/dist/Directives/Linkify.js +1 -1
  112. package/dist/Directives/Linkify.js.map +1 -1
  113. package/dist/Directives/Tooltip.js +2 -2
  114. package/dist/Directives/Tooltip.js.map +1 -1
  115. package/dist/Functions/usernameToColor.js +2 -3
  116. package/dist/Functions/usernameToColor.js.map +1 -1
  117. package/dist/Mixins/excludeClickOutsideClasses.js +2 -2
  118. package/dist/Mixins/excludeClickOutsideClasses.js.map +1 -1
  119. package/dist/Mixins/isFullscreen.js +1 -1
  120. package/dist/Mixins/isFullscreen.js.map +1 -1
  121. package/dist/Mixins/isMobile.js +1 -1
  122. package/dist/Mixins/isMobile.js.map +1 -1
  123. package/dist/Mixins/richEditor.js +1 -1
  124. package/dist/Mixins/richEditor.js.map +1 -1
  125. package/dist/ncvuecomponents.js +276 -69
  126. package/dist/ncvuecomponents.js.map +1 -1
  127. package/package.json +28 -43
  128. package/src/assets/action.scss +0 -132
  129. package/src/assets/iconfont/README.md +0 -30
  130. package/src/assets/iconfont/arrow-left-double.svg +0 -3
  131. package/src/assets/iconfont/arrow-left.svg +0 -3
  132. package/src/assets/iconfont/arrow-right-double.svg +0 -3
  133. package/src/assets/iconfont/arrow-right.svg +0 -3
  134. package/src/assets/iconfont/breadcrumb.svg +0 -1
  135. package/src/assets/iconfont/checkmark.svg +0 -1
  136. package/src/assets/iconfont/close.svg +0 -1
  137. package/src/assets/iconfont/confirm.svg +0 -1
  138. package/src/assets/iconfont/info.svg +0 -1
  139. package/src/assets/iconfont/menu.svg +0 -1
  140. package/src/assets/iconfont/more.svg +0 -1
  141. package/src/assets/iconfont/pause.svg +0 -1
  142. package/src/assets/iconfont/play.svg +0 -1
  143. package/src/assets/iconfont/triangle-s.svg +0 -1
  144. package/src/assets/iconfont/user-status-away.svg +0 -2
  145. package/src/assets/iconfont/user-status-dnd.svg +0 -2
  146. package/src/assets/iconfont/user-status-invisible.svg +0 -2
  147. package/src/assets/iconfont/user-status-online.svg +0 -2
  148. package/src/assets/inputs.scss +0 -104
  149. package/src/assets/variables.scss +0 -57
  150. package/src/components/ActionButton/ActionButton.vue +0 -160
  151. package/src/components/ActionButton/index.js +0 -24
  152. package/src/components/ActionCheckbox/ActionCheckbox.vue +0 -220
  153. package/src/components/ActionCheckbox/index.js +0 -24
  154. package/src/components/ActionInput/ActionInput.vue +0 -418
  155. package/src/components/ActionInput/index.js +0 -24
  156. package/src/components/ActionLink/ActionLink.vue +0 -132
  157. package/src/components/ActionLink/index.js +0 -24
  158. package/src/components/ActionRadio/ActionRadio.vue +0 -219
  159. package/src/components/ActionRadio/index.js +0 -24
  160. package/src/components/ActionRouter/ActionRouter.vue +0 -100
  161. package/src/components/ActionRouter/index.js +0 -24
  162. package/src/components/ActionSeparator/ActionSeparator.vue +0 -43
  163. package/src/components/ActionSeparator/index.js +0 -24
  164. package/src/components/ActionText/ActionText.vue +0 -87
  165. package/src/components/ActionText/index.js +0 -24
  166. package/src/components/ActionTextEditable/ActionTextEditable.vue +0 -306
  167. package/src/components/ActionTextEditable/index.js +0 -24
  168. package/src/components/Actions/Actions.vue +0 -764
  169. package/src/components/Actions/index.js +0 -24
  170. package/src/components/AppContent/AppContent.vue +0 -93
  171. package/src/components/AppContent/index.js +0 -23
  172. package/src/components/AppContentDetails/AppContentDetails.vue +0 -34
  173. package/src/components/AppContentDetails/index.js +0 -23
  174. package/src/components/AppContentList/AppContentList.vue +0 -44
  175. package/src/components/AppContentList/index.js +0 -23
  176. package/src/components/AppNavigation/AppNavigation.vue +0 -190
  177. package/src/components/AppNavigation/index.js +0 -23
  178. package/src/components/AppNavigationCaption/AppNavigationCaption.vue +0 -39
  179. package/src/components/AppNavigationCaption/index.js +0 -3
  180. package/src/components/AppNavigationCounter/AppNavigationCounter.vue +0 -82
  181. package/src/components/AppNavigationCounter/index.js +0 -25
  182. package/src/components/AppNavigationIconBullet/AppNavigationIconBullet.vue +0 -95
  183. package/src/components/AppNavigationIconBullet/index.js +0 -24
  184. package/src/components/AppNavigationItem/AppNavigationIconCollapsible.vue +0 -90
  185. package/src/components/AppNavigationItem/AppNavigationItem.vue +0 -629
  186. package/src/components/AppNavigationItem/InputConfirmCancel.vue +0 -134
  187. package/src/components/AppNavigationItem/index.js +0 -24
  188. package/src/components/AppNavigationNew/AppNavigationNew.vue +0 -76
  189. package/src/components/AppNavigationNew/index.js +0 -23
  190. package/src/components/AppNavigationNewItem/AppNavigationNewItem.vue +0 -165
  191. package/src/components/AppNavigationNewItem/index.js +0 -24
  192. package/src/components/AppNavigationSettings/AppNavigationSettings.vue +0 -105
  193. package/src/components/AppNavigationSettings/index.js +0 -23
  194. package/src/components/AppNavigationSpacer/AppNavigationSpacer.vue +0 -39
  195. package/src/components/AppNavigationSpacer/index.js +0 -23
  196. package/src/components/AppNavigationToggle/AppNavigationToggle.vue +0 -78
  197. package/src/components/AppNavigationToggle/index.js +0 -24
  198. package/src/components/AppSettingsDialog/AppSettingsDialog.vue +0 -331
  199. package/src/components/AppSettingsDialog/index.js +0 -25
  200. package/src/components/AppSettingsSection/AppSettingsSection.vue +0 -64
  201. package/src/components/AppSettingsSection/index.js +0 -25
  202. package/src/components/AppSidebar/AppSidebar.vue +0 -802
  203. package/src/components/AppSidebar/AppSidebarTabs.vue +0 -348
  204. package/src/components/AppSidebar/index.js +0 -23
  205. package/src/components/AppSidebarTab/AppSidebarTab.vue +0 -103
  206. package/src/components/AppSidebarTab/index.js +0 -23
  207. package/src/components/Avatar/Avatar.vue +0 -758
  208. package/src/components/Avatar/index.js +0 -25
  209. package/src/components/Breadcrumb/Breadcrumb.vue +0 -262
  210. package/src/components/Breadcrumb/index.js +0 -25
  211. package/src/components/Breadcrumbs/Breadcrumbs.vue +0 -537
  212. package/src/components/Breadcrumbs/index.js +0 -25
  213. package/src/components/ColorPicker/ColorPicker.vue +0 -380
  214. package/src/components/ColorPicker/index.js +0 -25
  215. package/src/components/Content/Content.vue +0 -77
  216. package/src/components/Content/index.js +0 -23
  217. package/src/components/DatetimePicker/DatetimePicker.vue +0 -195
  218. package/src/components/DatetimePicker/index.js +0 -28
  219. package/src/components/DatetimePicker/index.scss +0 -405
  220. package/src/components/EmojiPicker/EmojiPicker.vue +0 -302
  221. package/src/components/EmojiPicker/index.js +0 -23
  222. package/src/components/EmptyContent/EmptyContent.vue +0 -120
  223. package/src/components/EmptyContent/index.js +0 -24
  224. package/src/components/Highlight/Highlight.vue +0 -183
  225. package/src/components/Highlight/index.js +0 -25
  226. package/src/components/ListItemIcon/ListItemIcon.vue +0 -277
  227. package/src/components/ListItemIcon/index.js +0 -25
  228. package/src/components/Modal/Modal.vue +0 -833
  229. package/src/components/Modal/index.js +0 -27
  230. package/src/components/Multiselect/EllipsisedOption.vue +0 -141
  231. package/src/components/Multiselect/Multiselect.vue +0 -430
  232. package/src/components/Multiselect/index.js +0 -28
  233. package/src/components/Multiselect/index.scss +0 -290
  234. package/src/components/MultiselectTags/MultiselectTags.vue +0 -179
  235. package/src/components/MultiselectTags/api.js +0 -115
  236. package/src/components/MultiselectTags/index.js +0 -23
  237. package/src/components/Popover/Popover.vue +0 -208
  238. package/src/components/Popover/index.js +0 -25
  239. package/src/components/PopoverMenu/PopoverMenu.vue +0 -62
  240. package/src/components/PopoverMenu/PopoverMenuItem.vue +0 -382
  241. package/src/components/PopoverMenu/index.js +0 -24
  242. package/src/components/ProgressBar/ProgressBar.vue +0 -135
  243. package/src/components/ProgressBar/index.js +0 -25
  244. package/src/components/RichContenteditable/AutoCompleteResult.vue +0 -191
  245. package/src/components/RichContenteditable/MentionBubble.vue +0 -165
  246. package/src/components/RichContenteditable/RichContenteditable.vue +0 -517
  247. package/src/components/RichContenteditable/index.js +0 -25
  248. package/src/components/SettingsInputText/SettingsInputText.vue +0 -207
  249. package/src/components/SettingsInputText/index.js +0 -24
  250. package/src/components/SettingsSection/SettingsSection.vue +0 -151
  251. package/src/components/SettingsSection/index.js +0 -24
  252. package/src/components/SettingsSelectGroup/SettingsSelectGroup.vue +0 -149
  253. package/src/components/SettingsSelectGroup/index.js +0 -25
  254. package/src/components/UserBubble/UserBubble.vue +0 -319
  255. package/src/components/UserBubble/index.js +0 -25
  256. package/src/components/index.js +0 -110
  257. package/src/directives/Focus/index.js +0 -29
  258. package/src/directives/Linkify/index.js +0 -31
  259. package/src/directives/Tooltip/index.js +0 -32
  260. package/src/directives/Tooltip/index.scss +0 -117
  261. package/src/directives/index.js +0 -31
  262. package/src/fonts/iconfont-vue-f56d517.eot +0 -0
  263. package/src/fonts/iconfont-vue-f56d517.svg +0 -1
  264. package/src/fonts/iconfont-vue-f56d517.ttf +0 -0
  265. package/src/fonts/iconfont-vue-f56d517.woff +0 -0
  266. package/src/fonts/scss/iconfont-vue.scss +0 -115
  267. package/src/functions/usernameToColor/index.js +0 -25
  268. package/src/functions/usernameToColor/usernameToColor.js +0 -68
  269. package/src/index.js +0 -40
  270. package/src/l10n.js +0 -42
  271. package/src/mixins/actionGlobal.js +0 -59
  272. package/src/mixins/actionText.js +0 -85
  273. package/src/mixins/excludeClickOutsideClasses/index.js +0 -72
  274. package/src/mixins/index.js +0 -35
  275. package/src/mixins/isFullscreen/index.js +0 -46
  276. package/src/mixins/isMobile/index.js +0 -43
  277. package/src/mixins/l10n.js +0 -8
  278. package/src/mixins/richEditor/index.js +0 -160
  279. package/src/mixins/userStatus.js +0 -76
  280. package/src/utils/FindRanges.js +0 -47
  281. package/src/utils/GenColors.js +0 -79
  282. package/src/utils/GenRandomId.js +0 -31
  283. package/src/utils/GetChildren.js +0 -47
  284. package/src/utils/GetParent.js +0 -41
  285. package/src/utils/IsMobileState.js +0 -49
  286. package/src/utils/IsOutOfViewport.js +0 -36
  287. package/src/utils/ScopeComponent.js +0 -37
  288. package/src/utils/Timer.js +0 -61
  289. package/src/utils/ValidateChildren.js +0 -50
  290. package/src/utils/ValidateSlot.js +0 -57
@@ -1,23 +0,0 @@
1
- /**
2
- * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
3
- *
4
- * @author John Molakvoæ <skjnldsv@protonmail.com>
5
- *
6
- * @license GNU AGPL version 3 or any later version
7
- *
8
- * This program is free software: you can redistribute it and/or modify
9
- * it under the terms of the GNU Affero General Public License as
10
- * published by the Free Software Foundation, either version 3 of the
11
- * License, or (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU Affero General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU Affero General Public License
19
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
20
- */
21
- import AppSidebarTab from './AppSidebarTab'
22
-
23
- export default AppSidebarTab
@@ -1,758 +0,0 @@
1
- <!--
2
- - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
3
- -
4
- - @author Julius Härtl <jus@bitgrid.net>
5
- -
6
- - @license GNU AGPL version 3 or any later version
7
- -
8
- - This program is free software: you can redistribute it and/or modify
9
- - it under the terms of the GNU Affero General Public License as
10
- - published by the Free Software Foundation, either version 3 of the
11
- - License, or (at your option) any later version.
12
- -
13
- - This program is distributed in the hope that it will be useful,
14
- - but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- - GNU Affero General Public License for more details.
17
- -
18
- - You should have received a copy of the GNU Affero General Public License
19
- - along with this program. If not, see <http://www.gnu.org/licenses/>.
20
- -
21
- -->
22
-
23
- <docs>
24
-
25
- ### Basic user avatar
26
-
27
- ```vue
28
- <avatar user="janedoe" display-name="Jane Doe" />
29
- ```
30
-
31
- ### Avatar with image
32
-
33
- ```vue
34
- <avatar url="https://nextcloud.com/wp-content/themes/next/assets/img/common/nextcloud-square-logo.png" />
35
- ```
36
-
37
- </docs>
38
- <template>
39
- <div v-tooltip="tooltip"
40
- v-click-outside="closeMenu"
41
- :class="{
42
- 'avatardiv--unknown': userDoesNotExist,
43
- 'avatardiv--with-menu': hasMenu
44
- }"
45
- :style="avatarStyle"
46
- class="avatardiv popovermenu-wrapper"
47
- v-on="!disableMenu ? { click: toggleMenu } : {}">
48
- <!-- Avatar icon or image -->
49
- <div v-if="iconClass" :class="iconClass" class="avatar-class-icon" />
50
- <img v-else-if="isAvatarLoaded && !userDoesNotExist"
51
- :src="avatarUrlLoaded"
52
- :srcset="avatarSrcSetLoaded"
53
- alt="">
54
- <Popover
55
- v-if="hasMenu"
56
- placement="auto"
57
- :container="menuContainer"
58
- :open="contactsMenuOpenState">
59
- <PopoverMenu :menu="menu" />
60
- <template slot="trigger">
61
- <div :class="contactsMenuLoading ? 'icon-loading' : 'icon-more'" :style="{'width': size + 'px', 'height': size + 'px'}" />
62
- </template>
63
- </Popover>
64
-
65
- <!-- Avatar status -->
66
- <div v-if="showUserStatusIconOnAvatar" class="avatardiv__user-status avatardiv__user-status--icon">
67
- {{ userStatus.icon }}
68
- </div>
69
- <div v-else-if="canDisplayUserStatus"
70
- class="avatardiv__user-status"
71
- :class="'avatardiv__user-status--' + userStatus.status" />
72
- <div v-else-if="status"
73
- class="avatardiv__status"
74
- :class="'avatardiv__status--' + status"
75
- :style="{ backgroundColor: `#${statusColor}` }">
76
- <!-- triangle -->
77
- <svg v-if="status === 'neutral'"
78
- xmlns="http://www.w3.org/2000/svg"
79
- width="12"
80
- height="11"
81
- viewBox="0 0 3.175 2.91">
82
- <path d="M3.21 3.043H.494l.679-1.177.68-1.176.678 1.176z"
83
- :style="{ fill: `#${statusColor}` }"
84
- stroke="#fff"
85
- stroke-width=".265"
86
- stroke-linecap="square" />
87
- </svg>
88
- </div>
89
-
90
- <!-- Show the letter if no avatar nor icon class -->
91
- <div v-if="userDoesNotExist && !iconClass" class="unknown">
92
- {{ initials }}
93
- </div>
94
- </div>
95
- </template>
96
-
97
- <script>
98
- import { getBuilder } from '@nextcloud/browser-storage'
99
- import { directive as ClickOutside } from 'v-click-outside'
100
- import PopoverMenu from '../PopoverMenu'
101
- import { getCurrentUser } from '@nextcloud/auth'
102
- import { subscribe, unsubscribe } from '@nextcloud/event-bus'
103
- import axios from '@nextcloud/axios'
104
- import { generateUrl } from '@nextcloud/router'
105
- import Tooltip from '../../directives/Tooltip'
106
- import usernameToColor from '../../functions/usernameToColor'
107
- import { userStatus } from '../../mixins'
108
- import Popover from '../Popover/Popover'
109
-
110
- const browserStorage = getBuilder('nextcloud').persist().build()
111
-
112
- function getUserHasAvatar(userId) {
113
- const flag = browserStorage.getItem('user-has-avatar.' + userId)
114
- if (typeof flag === 'string') {
115
- return Boolean(flag)
116
- }
117
- return null
118
- }
119
-
120
- function setUserHasAvatar(userId, flag) {
121
- if (userId) {
122
- browserStorage.setItem('user-has-avatar.' + userId, flag)
123
- }
124
- }
125
-
126
- export default {
127
- name: 'Avatar',
128
-
129
- directives: {
130
- tooltip: Tooltip,
131
- ClickOutside,
132
- },
133
- components: {
134
- Popover,
135
- PopoverMenu,
136
- },
137
- mixins: [userStatus],
138
- props: {
139
- /**
140
- * Set a custom url to the avatar image
141
- * either the url, user or displayName property must be defined
142
- */
143
- url: {
144
- type: String,
145
- default: undefined,
146
- },
147
- /**
148
- * Set a css icon-class for an icon to be used instead of the avatar.
149
- */
150
- iconClass: {
151
- type: String,
152
- default: undefined,
153
- },
154
- /**
155
- * Set the user id to fetch the avatar
156
- * either the url, user or displayName property must be defined
157
- */
158
- user: {
159
- type: String,
160
- default: undefined,
161
- },
162
- /**
163
- * Whether or not to display the user-status
164
- */
165
- showUserStatus: {
166
- type: Boolean,
167
- default: true,
168
- },
169
- /**
170
- * Whether or not to the status-icon should be used instead of online/away
171
- */
172
- showUserStatusCompact: {
173
- type: Boolean,
174
- default: true,
175
- },
176
- /**
177
- * When the user status was preloaded via another source it can be handed in with this property to save the request.
178
- * If this property is not set the status will be fetched automatically.
179
- * If a preloaded no-status is available provide this object with properties "status", "icon" and "message" set to null.
180
- */
181
- preloadedUserStatus: {
182
- type: Object,
183
- default: undefined,
184
- },
185
- /**
186
- * Is the user a guest user (then we have to user a different endpoint)
187
- */
188
- isGuest: {
189
- type: Boolean,
190
- default: false,
191
- },
192
- /**
193
- * Set a display name that will be rendered as a tooltip
194
- * either the url, user or displayName property must be defined
195
- * specify just the displayname to generate a placeholder avatar without
196
- * trying to fetch the avatar based on the user id
197
- */
198
- displayName: {
199
- type: String,
200
- default: undefined,
201
- },
202
- /**
203
- * Set a size in px for the rendered avatar
204
- */
205
- size: {
206
- type: Number,
207
- default: 32,
208
- },
209
- /**
210
- * Placeholder avatars will be automatically generated when this is set to true
211
- */
212
- allowPlaceholder: {
213
- type: Boolean,
214
- default: true,
215
- },
216
- /**
217
- * Disable the tooltip
218
- */
219
- disableTooltip: {
220
- type: Boolean,
221
- default: false,
222
- },
223
- /**
224
- * Disable the menu
225
- */
226
- disableMenu: {
227
- type: Boolean,
228
- default: false,
229
- },
230
- /**
231
- * Declares a custom tooltip when not null
232
- * Fallback will be the displayName
233
- *
234
- * requires disableTooltip not to be set to true
235
- */
236
- tooltipMessage: {
237
- type: String,
238
- default: null,
239
- },
240
- /**
241
- * Declares username is not a user's name, when true.
242
- * Prevents loading user's avatar from server and forces generating colored initials,
243
- * i.e. if the user is a group
244
- */
245
- isNoUser: {
246
- type: Boolean,
247
- default: false,
248
- },
249
-
250
- /**
251
- * DEPRECATED!
252
- * This prop will be removed with nc/vue 3.0
253
- *
254
- * Declares a status indicator on the avatar
255
- * Available options are `positive`, `negative`, `neutral`
256
- */
257
- status: {
258
- type: String,
259
- default: null,
260
- validator: (value) => {
261
- switch (value) {
262
- case 'positive':
263
- case 'negative':
264
- case 'neutral':
265
- return true
266
- }
267
- return false
268
- },
269
- },
270
- /**
271
- * Declares a different color to be used with the status indicator
272
- */
273
- statusColor: {
274
- type: [Number, String],
275
- default: null,
276
- validator: value => {
277
- return /^([a-f0-9]{3}){1,2}$/i.test(value)
278
- },
279
- },
280
- /**
281
- * Choose the avatar menu alignment.
282
- * Possible values are `left`, `center`, `right`.
283
- */
284
- menuPosition: {
285
- type: String,
286
- default: 'center',
287
- },
288
-
289
- /**
290
- * Selector for the popover menu container
291
- */
292
- menuContainer: {
293
- type: String,
294
- default: 'body',
295
- },
296
- },
297
- data() {
298
- return {
299
- avatarUrlLoaded: null,
300
- avatarSrcSetLoaded: null,
301
- userDoesNotExist: false,
302
- isAvatarLoaded: false,
303
- isMenuLoaded: false,
304
- contactsMenuLoading: false,
305
- contactsMenuActions: [],
306
- contactsMenuOpenState: false,
307
- }
308
- },
309
- computed: {
310
- canDisplayUserStatus() {
311
- return this.showUserStatus
312
- && this.hasStatus
313
- && ['online', 'away', 'dnd'].includes(this.userStatus.status)
314
- },
315
- showUserStatusIconOnAvatar() {
316
- return this.showUserStatus
317
- && this.showUserStatusCompact
318
- && this.hasStatus
319
- && this.userStatus.status !== 'dnd'
320
- && this.userStatus.icon
321
- },
322
- getUserIdentifier() {
323
- if (this.isDisplayNameDefined) {
324
- return this.displayName
325
- }
326
- if (this.isUserDefined) {
327
- return this.user
328
- }
329
- return ''
330
- },
331
- isUserDefined() {
332
- return typeof this.user !== 'undefined'
333
- },
334
- isDisplayNameDefined() {
335
- return typeof this.displayName !== 'undefined'
336
- },
337
- isUrlDefined() {
338
- return typeof this.url !== 'undefined'
339
- },
340
- hasMenu() {
341
- if (this.disableMenu) {
342
- return false
343
- }
344
- if (this.isMenuLoaded) {
345
- return this.menu.length > 0
346
- }
347
- return !(this.user === getCurrentUser()?.uid || this.userDoesNotExist || this.url)
348
- },
349
- shouldShowPlaceholder() {
350
- return this.allowPlaceholder && (
351
- this.userDoesNotExist)
352
- },
353
- avatarStyle() {
354
- const style = {
355
- width: this.size + 'px',
356
- height: this.size + 'px',
357
- lineHeight: this.size + 'px',
358
- fontSize: Math.round(this.size * 0.55) + 'px',
359
- }
360
-
361
- if (!this.iconClass && !this.avatarSrcSetLoaded) {
362
- const rgb = usernameToColor(this.getUserIdentifier)
363
- style.backgroundColor = 'rgb(' + rgb.r + ', ' + rgb.g + ', ' + rgb.b + ')'
364
- }
365
- return style
366
- },
367
- tooltip() {
368
- if (this.disableTooltip) {
369
- return false
370
- }
371
- if (this.tooltipMessage) {
372
- return this.tooltipMessage
373
- }
374
-
375
- return this.displayName
376
- },
377
- initials() {
378
- let initials
379
- if (this.shouldShowPlaceholder) {
380
- const user = this.getUserIdentifier
381
- const idx = user.indexOf(' ')
382
- if (user === '') {
383
- initials = '?'
384
- } else {
385
- initials = String.fromCodePoint(user.codePointAt(0))
386
- if (idx !== -1) {
387
- initials = initials.concat(String.fromCodePoint(user.codePointAt(idx + 1)))
388
- }
389
- }
390
- }
391
- return initials.toUpperCase()
392
- },
393
- menu() {
394
- const actions = this.contactsMenuActions.map((item) => {
395
- return {
396
- href: item.hyperlink,
397
- icon: item.icon,
398
- longtext: item.title,
399
- }
400
- })
401
-
402
- function escape(html) {
403
- const text = document.createTextNode(html)
404
- const p = document.createElement('p')
405
- p.appendChild(text)
406
- return p.innerHTML
407
- }
408
-
409
- if (this.showUserStatus && (this.userStatus.icon || this.userStatus.message)) {
410
- return [{
411
- href: '#',
412
- icon: `data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><text x='0' y='14' font-size='14'>${escape(this.userStatus.icon)}</text></svg>`,
413
- text: `${this.userStatus.message}`,
414
- }].concat(actions)
415
- }
416
-
417
- return actions
418
- },
419
- },
420
-
421
- watch: {
422
- url() {
423
- this.userDoesNotExist = false
424
- this.loadAvatarUrl()
425
- },
426
- user() {
427
- this.userDoesNotExist = false
428
- this.isMenuLoaded = false
429
- this.loadAvatarUrl()
430
- },
431
- },
432
-
433
- mounted() {
434
- this.loadAvatarUrl()
435
- if (this.showUserStatus && this.user && !this.isNoUser) {
436
- if (!this.preloadedUserStatus) {
437
- this.fetchUserStatus(this.user)
438
- } else {
439
- this.userStatus.status = this.preloadedUserStatus.status || ''
440
- this.userStatus.message = this.preloadedUserStatus.message || ''
441
- this.userStatus.icon = this.preloadedUserStatus.icon || ''
442
- this.hasStatus = this.preloadedUserStatus.status !== null
443
- }
444
- subscribe('user_status:status.updated', this.handleUserStatusUpdated)
445
- }
446
- },
447
-
448
- beforeDestroyed() {
449
- if (this.showUserStatus && this.user && !this.isNoUser) {
450
- unsubscribe('user_status:status.updated', this.handleUserStatusUpdated)
451
- }
452
- },
453
-
454
- methods: {
455
- handleUserStatusUpdated(state) {
456
- if (this.user === state.userId) {
457
- this.userStatus = {
458
- status: state.status,
459
- icon: state.icon,
460
- message: state.message,
461
- }
462
- }
463
- },
464
-
465
- async toggleMenu() {
466
- if (!this.hasMenu) {
467
- return
468
- }
469
- if (!this.contactsMenuOpenState) {
470
- await this.fetchContactsMenu()
471
- }
472
- this.contactsMenuOpenState = !this.contactsMenuOpenState
473
- },
474
- closeMenu() {
475
- this.contactsMenuOpenState = false
476
- },
477
- async fetchContactsMenu() {
478
- this.contactsMenuLoading = true
479
- try {
480
- const user = encodeURIComponent(this.user)
481
- const { data } = await axios.post(generateUrl('contactsmenu/findOne'), `shareType=0&shareWith=${user}`)
482
- this.contactsMenuActions = data.topAction ? [data.topAction].concat(data.actions) : data.actions
483
- } catch (e) {
484
- this.contactsMenuOpenState = false
485
- }
486
- this.contactsMenuLoading = false
487
- this.isMenuLoaded = true
488
- },
489
-
490
- /**
491
- * Handle avatar loading if user or url defined
492
- */
493
- loadAvatarUrl() {
494
- this.isAvatarLoaded = false
495
-
496
- /** Only run avatar image loading if either user or url property is defined */
497
- if (!this.isUrlDefined && (!this.isUserDefined || this.isNoUser)) {
498
- this.isAvatarLoaded = true
499
- this.userDoesNotExist = true
500
- return
501
- }
502
-
503
- // Directly use the url if defined
504
- if (this.isUrlDefined) {
505
- this.updateImageIfValid(this.url)
506
- return
507
- }
508
-
509
- const avatarUrl = this.avatarUrlGenerator(this.user, this.size)
510
- const srcset = [
511
- avatarUrl + ' 1x',
512
- this.avatarUrlGenerator(this.user, this.size * 2) + ' 2x',
513
- this.avatarUrlGenerator(this.user, this.size * 4) + ' 4x',
514
- ].join(', ')
515
-
516
- this.updateImageIfValid(avatarUrl, srcset)
517
- },
518
-
519
- /**
520
- * Generate an avatar url from the server's avatar endpoint
521
- *
522
- * @param {string} user the user id
523
- * @param {number} size the desired size
524
- * @returns {string}
525
- */
526
- avatarUrlGenerator(user, size) {
527
- let url = '/avatar/{user}/{size}'
528
- if (this.isGuest) {
529
- url = '/avatar/guest/{user}/{size}'
530
- }
531
-
532
- let avatarUrl = generateUrl(
533
- url,
534
- {
535
- user,
536
- size,
537
- })
538
-
539
- // eslint-disable-next-line camelcase
540
- if (user === getCurrentUser()?.uid && typeof oc_userconfig !== 'undefined') {
541
- avatarUrl += '?v=' + oc_userconfig.avatar.version
542
- }
543
-
544
- return avatarUrl
545
- },
546
-
547
- /**
548
- * Check if the provided url is valid and update Avatar if so
549
- *
550
- * @param {string} url the avatar url
551
- * @param {array} srcset the avatar srcset
552
- */
553
- updateImageIfValid(url, srcset = null) {
554
- // skip loading
555
- const userHasAvatar = getUserHasAvatar(this.user)
556
- if (this.isUserDefined && typeof userHasAvatar === 'boolean') {
557
- this.isAvatarLoaded = true
558
- this.avatarUrlLoaded = url
559
- if (srcset) {
560
- this.avatarSrcSetLoaded = srcset
561
- }
562
- if (userHasAvatar === false) {
563
- this.userDoesNotExist = true
564
- }
565
- return
566
- }
567
-
568
- const img = new Image()
569
- img.onload = () => {
570
- this.avatarUrlLoaded = url
571
- if (srcset) {
572
- this.avatarSrcSetLoaded = srcset
573
- }
574
- this.isAvatarLoaded = true
575
- // re-get to avoid concurrent access
576
- setUserHasAvatar(this.user, true)
577
- }
578
- img.onerror = () => {
579
- console.debug('Invalid avatar url', url)
580
- // Avatar is invalid, reset
581
- this.avatarUrlLoaded = null
582
- this.avatarSrcSetLoaded = null
583
-
584
- this.userDoesNotExist = true
585
- this.isAvatarLoaded = false
586
- setUserHasAvatar(this.user, false)
587
- }
588
-
589
- if (srcset) {
590
- img.srcset = srcset
591
- }
592
- img.src = url
593
- },
594
- },
595
- }
596
- </script>
597
-
598
- <style scoped lang="scss">
599
- @import '../../fonts/scss/iconfont-vue';
600
-
601
- .avatardiv {
602
- position: relative;
603
- display: inline-block;
604
-
605
- &--unknown {
606
- position: relative;
607
- background-color: var(--color-text-maxcontrast);
608
- }
609
-
610
- &:not(&--unknown) {
611
- // White background for avatars with transparency
612
- background-color: #fff !important;
613
- body.theme--dark & {
614
- // And black background in dark mode, as it shines through on hover of the menu
615
- background-color: #000 !important;
616
- }
617
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.05) inset;
618
- }
619
-
620
- &--with-menu {
621
- cursor: pointer;
622
- ::v-deep .trigger {
623
- position: absolute;
624
- top: 0;
625
- left: 0;
626
- }
627
- .icon-more, .icon-loading {
628
- display: flex;
629
- cursor: pointer;
630
- background: none;
631
- font-size: 18px;
632
- align-items: center;
633
- justify-content: center;
634
-
635
- @include iconfont('more');
636
- &::before {
637
- display: block;
638
- }
639
- }
640
- .icon-more {
641
- opacity: 0;
642
- }
643
- &:focus,
644
- &:hover {
645
- .icon-more {
646
- opacity: 1;
647
- }
648
- img {
649
- opacity: 0.3;
650
- }
651
- }
652
- .icon-more,
653
- img {
654
- transition: opacity var(--animation-quick);
655
- }
656
- }
657
-
658
- > .unknown {
659
- position: absolute;
660
- top: 0;
661
- left: 0;
662
- display: block;
663
- width: 100%;
664
- text-align: center;
665
- font-weight: normal;
666
- color: var(--color-main-background);
667
- }
668
-
669
- img {
670
- // Cover entire area
671
- width: 100%;
672
- height: 100%;
673
- // Keep ratio
674
- object-fit: cover;
675
- }
676
-
677
- .avatardiv__status {
678
- position: absolute;
679
- top: 22px;
680
- left: 22px;
681
- width: 10px;
682
- height: 10px;
683
- border: 1px solid rgba(255, 255, 255, .5);
684
- background-clip: content-box;
685
- &--positive {
686
- border-radius: 50%;
687
- background-color: var(--color-success);
688
- }
689
- &--negative {
690
- background-color: var(--color-error);
691
- }
692
- &--neutral {
693
- border: none;
694
- background-color: transparent !important;
695
- svg {
696
- position: absolute;
697
- top: -3px;
698
- left: -2px;
699
- path {
700
- fill: #aaa;
701
- }
702
- }
703
- }
704
- }
705
-
706
- .avatardiv__user-status {
707
- position: absolute;
708
- right: -4px;
709
- bottom: -4px;
710
- height: 18px;
711
- width: 18px;
712
- line-height: 15px;
713
- font-size: var(--default-font-size);
714
- border: 2px solid var(--color-main-background);
715
- background-color: var(--color-main-background);
716
- border-radius: 50%;
717
-
718
- .acli:hover & {
719
- border-color: var(--color-background-hover);
720
- background-color: var(--color-background-hover);
721
- }
722
- .acli.active & {
723
- border-color: var(--color-primary-light);
724
- background-color: var(--color-primary-light);
725
- }
726
-
727
- &--online{
728
- @include iconfont('user-status-online');
729
- color: #49b382;
730
- }
731
- &--dnd{
732
- @include iconfont('user-status-dnd');
733
- background-color: #ffffff;
734
- color: #ed484c;
735
- }
736
- &--away{
737
- @include iconfont('user-status-away');
738
- color: #f4a331;
739
- }
740
- &--icon {
741
- border: none;
742
- background-color: transparent;
743
- }
744
- }
745
-
746
- .popovermenu-wrapper {
747
- position: relative;
748
- display: inline-block;
749
- }
750
- }
751
-
752
- .avatar-class-icon {
753
- border-radius: 50%;
754
- background-color: var(--color-background-darker);
755
- height: 100%;
756
- }
757
-
758
- </style>