@nextcloud/vue 9.10.0 → 9.12.0

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 (155) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/assets/NcActionInput.css +66 -66
  3. package/dist/assets/NcActions.css +12 -12
  4. package/dist/assets/NcAppNavigationItem.css +54 -52
  5. package/dist/assets/NcAppNavigationList.css +2 -26
  6. package/dist/assets/NcAppNavigationNewItem.css +9 -7
  7. package/dist/assets/NcAppNavigationSettings.css +6 -6
  8. package/dist/assets/NcAppSettingsDialog.css +3 -3
  9. package/dist/assets/NcAppSettingsShortcutsSection.css +1 -1
  10. package/dist/assets/NcAppSidebar.css +130 -76
  11. package/dist/assets/NcAppSidebarTab.css +4 -4
  12. package/dist/assets/NcAssistantButton.css +9 -9
  13. package/dist/assets/NcAssistantContent.css +3 -3
  14. package/dist/assets/NcAssistantIcon.css +4 -4
  15. package/dist/assets/NcAvatar.css +26 -26
  16. package/dist/assets/NcBlurHash.css +2 -2
  17. package/dist/assets/NcDateTimePicker.css +234 -234
  18. package/dist/assets/NcFilePicker.css +1 -1
  19. package/dist/assets/NcFormBox.css +11 -11
  20. package/dist/assets/NcFormBoxButton.css +2 -2
  21. package/dist/assets/NcFormBoxItem.css +15 -15
  22. package/dist/assets/NcFormBoxSwitch.css +2 -2
  23. package/dist/assets/NcFormGroup.css +7 -7
  24. package/dist/assets/NcHotkey.css +8 -8
  25. package/dist/assets/NcHotkeyList.css +2 -2
  26. package/dist/assets/NcIconToggleSwitch.css +4 -4
  27. package/dist/assets/NcKbd.css +3 -3
  28. package/dist/assets/NcModal.css +69 -63
  29. package/dist/assets/NcPopover.css +16 -16
  30. package/dist/assets/NcProfileHoverCard.css +82 -59
  31. package/dist/assets/NcRadioGroup.css +2 -2
  32. package/dist/assets/NcRadioGroupButton.css +14 -14
  33. package/dist/assets/NcRichContenteditable.css +17 -17
  34. package/dist/assets/NcRichText.css +2 -2
  35. package/dist/assets/NcSelect.css +25 -0
  36. package/dist/assets/NcUploadPicker.css +41 -0
  37. package/dist/assets/autolink.css +3 -3
  38. package/dist/chunks/NcActionInput.mjs +4 -4
  39. package/dist/chunks/NcActionInput.mjs.map +1 -1
  40. package/dist/chunks/NcActions.mjs +4 -4
  41. package/dist/chunks/NcActions.mjs.map +1 -1
  42. package/dist/chunks/NcAppContent.mjs +4 -4
  43. package/dist/chunks/NcAppContent.mjs.map +1 -1
  44. package/dist/chunks/NcAppNavigation.mjs +2 -2
  45. package/dist/chunks/NcAppNavigationItem.mjs +6 -29
  46. package/dist/chunks/NcAppNavigationItem.mjs.map +1 -1
  47. package/dist/chunks/NcAppNavigationList.mjs +8 -138
  48. package/dist/chunks/NcAppNavigationList.mjs.map +1 -1
  49. package/dist/chunks/NcAppNavigationNewItem.mjs +1 -1
  50. package/dist/chunks/NcAppNavigationNewItem.mjs.map +1 -1
  51. package/dist/chunks/NcAppNavigationSearch.mjs +2 -2
  52. package/dist/chunks/NcAppNavigationSettings.mjs +8 -8
  53. package/dist/chunks/NcAppSettingsDialog.mjs +5 -5
  54. package/dist/chunks/NcAppSettingsShortcutsSection.mjs +3 -3
  55. package/dist/chunks/NcAppSidebar.mjs +165 -31
  56. package/dist/chunks/NcAppSidebar.mjs.map +1 -1
  57. package/dist/chunks/NcAppSidebarTab.mjs +12 -5
  58. package/dist/chunks/NcAppSidebarTab.mjs.map +1 -1
  59. package/dist/chunks/NcAssistantButton.mjs +7 -7
  60. package/dist/chunks/NcAssistantContent.mjs +3 -3
  61. package/dist/chunks/NcAssistantIcon.mjs +4 -4
  62. package/dist/chunks/NcAvatar.mjs +17 -4
  63. package/dist/chunks/NcAvatar.mjs.map +1 -1
  64. package/dist/chunks/NcBlurHash.mjs +2 -2
  65. package/dist/chunks/NcCheckboxRadioSwitch.mjs +1 -1
  66. package/dist/chunks/NcCollectionList.mjs +3 -3
  67. package/dist/chunks/NcColorPicker.mjs +2 -2
  68. package/dist/chunks/NcContent.mjs +2 -2
  69. package/dist/chunks/NcDashboardWidget.mjs +4 -4
  70. package/dist/chunks/NcDashboardWidget.mjs.map +1 -1
  71. package/dist/chunks/NcDateTimePicker.mjs +7 -4
  72. package/dist/chunks/NcDateTimePicker.mjs.map +1 -1
  73. package/dist/chunks/NcDateTimePickerNative.mjs +2 -2
  74. package/dist/chunks/NcDialogButton.vue_vue_type_script_setup_true_lang.mjs +2 -2
  75. package/dist/chunks/NcEmojiPicker.mjs +2 -2
  76. package/dist/chunks/NcFilePicker.mjs +6 -5
  77. package/dist/chunks/NcFilePicker.mjs.map +1 -1
  78. package/dist/chunks/NcFormBox.mjs +5 -5
  79. package/dist/chunks/NcFormBoxButton.mjs +2 -2
  80. package/dist/chunks/NcFormBoxItem.mjs +8 -8
  81. package/dist/chunks/NcFormBoxSwitch.mjs +2 -2
  82. package/dist/chunks/NcFormGroup.mjs +7 -7
  83. package/dist/chunks/NcHotkey.mjs +4 -4
  84. package/dist/chunks/NcHotkeyList.mjs +4 -4
  85. package/dist/chunks/NcIconToggleSwitch.mjs +2 -2
  86. package/dist/chunks/NcKbd.mjs +4 -4
  87. package/dist/chunks/NcModal.mjs +13 -8
  88. package/dist/chunks/NcModal.mjs.map +1 -1
  89. package/dist/chunks/NcPasswordField.mjs +2 -2
  90. package/dist/chunks/NcPopover.mjs +2 -2
  91. package/dist/chunks/NcProfileHoverCard.mjs +205 -157
  92. package/dist/chunks/NcProfileHoverCard.mjs.map +1 -1
  93. package/dist/chunks/NcRadioGroup.mjs +2 -2
  94. package/dist/chunks/NcRadioGroupButton.mjs +6 -6
  95. package/dist/chunks/NcReferenceWidget.mjs +2 -2
  96. package/dist/chunks/NcRelatedResourcesPanel.mjs +4 -4
  97. package/dist/chunks/NcRichContenteditable.mjs +12 -12
  98. package/dist/chunks/NcRichText.mjs +3 -3
  99. package/dist/chunks/NcRichText.mjs.map +1 -1
  100. package/dist/chunks/NcSelect.mjs +74 -5
  101. package/dist/chunks/NcSelect.mjs.map +1 -1
  102. package/dist/chunks/NcSettingsSection.mjs +2 -2
  103. package/dist/chunks/NcSettingsSelectGroup.mjs +2 -2
  104. package/dist/chunks/NcTextField.vue_vue_type_script_setup_true_lang.mjs +2 -2
  105. package/dist/chunks/NcTimezonePicker.vue_vue_type_script_setup_true_lang.mjs +2 -2
  106. package/dist/chunks/NcUploadPicker.mjs +269 -0
  107. package/dist/chunks/NcUploadPicker.mjs.map +1 -0
  108. package/dist/chunks/NcUserStatusIcon.mjs +2 -2
  109. package/dist/chunks/_l10n.mjs +86 -84
  110. package/dist/chunks/_l10n.mjs.map +1 -1
  111. package/dist/chunks/autolink.mjs +3 -3
  112. package/dist/chunks/colors.mjs +2 -2
  113. package/dist/chunks/mdi.mjs +7 -5
  114. package/dist/chunks/mdi.mjs.map +1 -1
  115. package/dist/chunks/referencePickerModal.mjs +5 -5
  116. package/dist/components/NcActionInput/NcActionInput.vue.d.ts +38 -10
  117. package/dist/components/NcActions/NcActions.vue.d.ts +1 -1
  118. package/dist/components/NcAppNavigationCaption/NcAppNavigationCaption.vue.d.ts +1 -1
  119. package/dist/components/NcAppNavigationItem/NcAppNavigationItem.vue.d.ts +1 -5
  120. package/dist/components/NcAppNavigationList/NcAppNavigationList.vue.d.ts +1 -57
  121. package/dist/components/NcAppSidebar/NcAppSidebar.vue.d.ts +20 -1
  122. package/dist/components/NcAppSidebar/NcAppSidebarTabs.vue.d.ts +43 -0
  123. package/dist/components/NcAppSidebar/NcAppSidebarTabsButton.vue.d.ts +5 -0
  124. package/dist/components/NcAppSidebarTab/NcAppSidebarTab.vue.d.ts +14 -4
  125. package/dist/components/NcAvatar/NcAvatar.vue.d.ts +10 -1
  126. package/dist/components/NcBreadcrumb/NcBreadcrumb.vue.d.ts +1 -1
  127. package/dist/components/NcBreadcrumbs/NcBreadcrumbs.vue.d.ts +2 -2
  128. package/dist/components/NcCollectionList/NcCollectionList.vue.d.ts +41 -5
  129. package/dist/components/NcCollectionList/NcCollectionListItem.vue.d.ts +6 -2
  130. package/dist/components/NcDashboardWidget/NcDashboardWidget.vue.d.ts +11 -3
  131. package/dist/components/NcDashboardWidgetItem/NcDashboardWidgetItem.vue.d.ts +6 -2
  132. package/dist/components/NcDateTimePicker/NcDateTimePicker.vue.d.ts +7 -7
  133. package/dist/components/NcFilePicker/NcFilePicker.vue.d.ts +7 -0
  134. package/dist/components/NcListItem/NcListItem.vue.d.ts +1 -1
  135. package/dist/components/NcListItemIcon/NcListItemIcon.vue.d.ts +6 -2
  136. package/dist/components/NcProfileHoverCard/NcProfileHoverCard.vue.d.ts +6 -0
  137. package/dist/components/NcRichText/NcReferencePicker/NcProviderList.vue.d.ts +30 -2
  138. package/dist/components/NcRichText/NcReferencePicker/NcReferencePicker.vue.d.ts +60 -4
  139. package/dist/components/NcRichText/NcReferencePicker/NcReferencePickerModal.vue.d.ts +60 -4
  140. package/dist/components/NcRichText/NcReferencePicker/NcSearch.vue.d.ts +30 -2
  141. package/dist/components/NcSelect/NcSelect.vue.d.ts +39 -2
  142. package/dist/components/NcSelectTags/NcSelectTags.vue.d.ts +30 -2
  143. package/dist/components/NcSettingsSelectGroup/NcSettingsSelectGroup.vue.d.ts +30 -2
  144. package/dist/components/NcUploadPicker/NcUploadPicker.vue.d.ts +180 -0
  145. package/dist/components/NcUploadPicker/index.d.ts +6 -0
  146. package/dist/components/NcUploadPicker/index.mjs +5 -0
  147. package/dist/components/NcUploadPicker/index.mjs.map +1 -0
  148. package/dist/components/index.d.ts +1 -0
  149. package/dist/composables/useFormatDateTime/index.mjs +2 -2
  150. package/dist/index.mjs +2 -0
  151. package/dist/index.mjs.map +1 -1
  152. package/package.json +25 -11
  153. package/dist/chunks/highlight.mjs +0 -5
  154. package/dist/chunks/highlight.mjs.map +0 -1
  155. package/dist/components/NcAppNavigationList/highlight.d.ts +0 -12
@@ -1,5 +1,5 @@
1
1
  import '../assets/NcProfileHoverCard.css';
2
- import { openBlock, createElementBlock, mergeProps, createElementVNode, toDisplayString, createCommentVNode, defineComponent, ref, computed, watch, onMounted, unref, createVNode, Fragment, createBlock, withCtx, createSlots, createTextVNode, normalizeClass, renderList, resolveDynamicComponent } from "vue";
2
+ import { openBlock, createElementBlock, mergeProps, createElementVNode, toDisplayString, createCommentVNode, defineComponent, ref, computed, watch, onMounted, unref, normalizeClass, createVNode, Fragment, createBlock, withCtx, resolveDynamicComponent, createSlots, createTextVNode, renderList } from "vue";
3
3
  import { getCurrentUser } from "@nextcloud/auth";
4
4
  import axios from "@nextcloud/axios";
5
5
  import { getCapabilities } from "@nextcloud/capabilities";
@@ -12,56 +12,12 @@ import { N as NcActionRouter } from "./NcActionRouter.mjs";
12
12
  import { N as NcActions } from "./NcActions.mjs";
13
13
  import { N as NcAvatar } from "./NcAvatar.mjs";
14
14
  import { N as NcButton } from "./NcButton.mjs";
15
- import { N as NcEmptyContent } from "./NcEmptyContent.mjs";
16
15
  import { N as NcLoadingIcon } from "./NcLoadingIcon.mjs";
17
16
  import { N as NcRichText } from "./NcRichText.mjs";
18
17
  import { useIsSmallMobile } from "../composables/useIsMobile/index.mjs";
19
- import { r as register, Q as t1, a as t } from "./_l10n.mjs";
18
+ import { r as register, R as t25, a as t } from "./_l10n.mjs";
20
19
  import { l as logger } from "./logger.mjs";
21
20
  import { N as NcIconSvgWrapper } from "./NcIconSvgWrapper.mjs";
22
- const _sfc_main$5 = {
23
- name: "AccountOutlineIcon",
24
- emits: ["click"],
25
- props: {
26
- title: {
27
- type: String
28
- },
29
- fillColor: {
30
- type: String,
31
- default: "currentColor"
32
- },
33
- size: {
34
- type: Number,
35
- default: 24
36
- }
37
- }
38
- };
39
- const _hoisted_1$5 = ["aria-hidden", "aria-label"];
40
- const _hoisted_2$5 = ["fill", "width", "height"];
41
- const _hoisted_3$5 = { d: "M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,6A2,2 0 0,0 10,8A2,2 0 0,0 12,10A2,2 0 0,0 14,8A2,2 0 0,0 12,6M12,13C14.67,13 20,14.33 20,17V20H4V17C4,14.33 9.33,13 12,13M12,14.9C9.03,14.9 5.9,16.36 5.9,17V18.1H18.1V17C18.1,16.36 14.97,14.9 12,14.9Z" };
42
- const _hoisted_4$5 = { key: 0 };
43
- function _sfc_render$4(_ctx, _cache, $props, $setup, $data, $options) {
44
- return openBlock(), createElementBlock("span", mergeProps(_ctx.$attrs, {
45
- "aria-hidden": $props.title ? null : "true",
46
- "aria-label": $props.title,
47
- class: "material-design-icon account-outline-icon",
48
- role: "img",
49
- onClick: _cache[0] || (_cache[0] = ($event) => _ctx.$emit("click", $event))
50
- }), [
51
- (openBlock(), createElementBlock("svg", {
52
- fill: $props.fillColor,
53
- class: "material-design-icon__svg",
54
- width: $props.size,
55
- height: $props.size,
56
- viewBox: "0 0 24 24"
57
- }, [
58
- createElementVNode("path", _hoisted_3$5, [
59
- $props.title ? (openBlock(), createElementBlock("title", _hoisted_4$5, toDisplayString($props.title), 1)) : createCommentVNode("", true)
60
- ])
61
- ], 8, _hoisted_2$5))
62
- ], 16, _hoisted_1$5);
63
- }
64
- const AccountIcon = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["render", _sfc_render$4]]);
65
21
  const _sfc_main$4 = {
66
22
  name: "BriefcaseOutlineIcon",
67
23
  emits: ["click"],
@@ -234,7 +190,7 @@ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
234
190
  ], 16, _hoisted_1$1);
235
191
  }
236
192
  const PencilIcon = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["render", _sfc_render]]);
237
- register(t1);
193
+ register(t25);
238
194
  /*!
239
195
  * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
240
196
  * SPDX-License-Identifier: AGPL-3.0-or-later
@@ -295,63 +251,65 @@ const _hoisted_5 = {
295
251
  };
296
252
  const _hoisted_6 = { class: "profile-hover-card__header__container__identity" };
297
253
  const _hoisted_7 = { class: "profile-hover-card__header__container__displayname" };
298
- const _hoisted_8 = {
299
- key: 0,
254
+ const _hoisted_8 = ["href"];
255
+ const _hoisted_9 = { key: 1 };
256
+ const _hoisted_10 = {
257
+ key: 2,
300
258
  class: "profile-hover-card__header__container__pronoun-separator"
301
259
  };
302
- const _hoisted_9 = {
303
- key: 1,
260
+ const _hoisted_11 = {
261
+ key: 3,
304
262
  class: "profile-hover-card__header__container__pronouns"
305
263
  };
306
- const _hoisted_10 = {
264
+ const _hoisted_12 = {
307
265
  key: 0,
308
266
  class: "profile-hover-card__header__container__status"
309
267
  };
310
- const _hoisted_11 = { class: "profile-hover-card__header__container__status-content" };
311
- const _hoisted_12 = { class: "profile-hover-card__body" };
312
- const _hoisted_13 = { class: "profile-hover-card__content" };
313
- const _hoisted_14 = { class: "profile-hover-card__sidebar" };
314
- const _hoisted_15 = { class: "user-actions" };
315
- const _hoisted_16 = {
268
+ const _hoisted_13 = { class: "profile-hover-card__header__container__status-content" };
269
+ const _hoisted_14 = { class: "profile-hover-card__body" };
270
+ const _hoisted_15 = { class: "profile-hover-card__content" };
271
+ const _hoisted_16 = { class: "profile-hover-card__sidebar" };
272
+ const _hoisted_17 = { class: "user-actions" };
273
+ const _hoisted_18 = {
316
274
  key: 0,
317
275
  class: "user-actions__loading"
318
276
  };
319
- const _hoisted_17 = ["src"];
320
- const _hoisted_18 = ["src"];
321
- const _hoisted_19 = { class: "profile-hover-card__blocks" };
322
- const _hoisted_20 = {
277
+ const _hoisted_19 = ["src"];
278
+ const _hoisted_20 = ["src"];
279
+ const _hoisted_21 = {
280
+ key: 0,
281
+ class: "profile-hover-card__blocks"
282
+ };
283
+ const _hoisted_22 = {
323
284
  key: 0,
324
285
  class: "profile-hover-card__blocks-details"
325
286
  };
326
- const _hoisted_21 = {
287
+ const _hoisted_23 = {
327
288
  key: 0,
328
289
  class: "detail"
329
290
  };
330
- const _hoisted_22 = { key: 0 };
331
- const _hoisted_23 = {
291
+ const _hoisted_24 = { key: 0 };
292
+ const _hoisted_25 = {
332
293
  key: 1,
333
294
  class: "detail"
334
295
  };
335
- const _hoisted_24 = {
296
+ const _hoisted_26 = {
336
297
  key: 2,
337
298
  class: "detail"
338
299
  };
339
- const _hoisted_25 = {
300
+ const _hoisted_27 = {
340
301
  key: 0,
341
302
  class: "profile-hover-card__blocks-headline"
342
303
  };
343
- const _hoisted_26 = {
304
+ const _hoisted_28 = {
344
305
  key: 1,
345
306
  class: "profile-hover-card__blocks-biography"
346
307
  };
347
- const _hoisted_27 = {
348
- key: 2,
349
- class: "profile-hover-card__error"
350
- };
351
308
  const _sfc_main = /* @__PURE__ */ defineComponent({
352
309
  __name: "NcProfileHoverCard",
353
310
  props: {
354
311
  user: { default: null },
312
+ displayName: { default: null },
355
313
  profile: { default: null },
356
314
  preloadedUserStatus: { default: null },
357
315
  open: { type: Boolean, default: false },
@@ -364,17 +322,62 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
364
322
  const error = ref(false);
365
323
  const profileData = ref(props.profile);
366
324
  const userStatus = ref(props.preloadedUserStatus ?? {});
325
+ const profileEnabled = ref(!!props.profile);
326
+ const userStatusReady = ref(props.preloadedUserStatus !== null);
367
327
  const isMobile = useIsSmallMobile();
328
+ const showLoading = computed(() => loading.value || !!profileData.value && !error.value && !userStatusReady.value);
368
329
  if (props.user && props.profile) {
369
330
  setCachedProfile(props.user, props.profile);
370
331
  }
371
332
  const isCurrentUser = computed(() => !!props.user && getCurrentUser()?.uid === props.user);
372
333
  const settingsUrl = generateUrl("/settings/user");
334
+ const profileUrl = computed(() => {
335
+ if (!profileEnabled.value) {
336
+ return null;
337
+ }
338
+ const userId = profileData.value?.userId || props.user;
339
+ if (!userId) {
340
+ return null;
341
+ }
342
+ return generateUrl("/u/{userId}", { userId });
343
+ });
344
+ const resolvedDisplayName = computed(() => profileData.value?.displayname || props.displayName || profileData.value?.userId || props.user || "");
345
+ const profileLinkProps = computed(() => {
346
+ if (!profileUrl.value) {
347
+ return {};
348
+ }
349
+ return {
350
+ href: profileUrl.value,
351
+ "aria-label": t("View profile")
352
+ };
353
+ });
354
+ function isSidebarAction(action) {
355
+ return action.appId !== "timezone" && action.appId !== "profile" && action.id !== "profile";
356
+ }
357
+ function actionDisplayText(action) {
358
+ if (isCurrentUser.value) {
359
+ return action.text;
360
+ }
361
+ if (action.id === "talk-call" || isSpreedDirectCallAction(action)) {
362
+ return t("Start call");
363
+ }
364
+ if (action.id === "talk" || action.appId === "spreed") {
365
+ return t("Send message");
366
+ }
367
+ return action.text;
368
+ }
369
+ function isSpreedDirectCallAction(action) {
370
+ if (action.appId !== "spreed") {
371
+ return false;
372
+ }
373
+ const href = action.href ?? (typeof action.to === "string" ? action.to : "");
374
+ return typeof href === "string" && href.includes("#direct-call");
375
+ }
373
376
  const resolvedActions = computed(() => {
374
377
  if (props.actions && props.actions.length > 0) {
375
- return props.actions.filter((action) => action.appId !== "timezone");
378
+ return props.actions.filter(isSidebarAction);
376
379
  }
377
- return (profileData.value?.actions ?? []).filter((action) => action.appId !== "timezone").map((action) => ({
380
+ return (profileData.value?.actions ?? []).filter(isSidebarAction).map((action) => ({
378
381
  id: action.id,
379
382
  appId: action.appId,
380
383
  text: action.title,
@@ -410,13 +413,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
410
413
  }
411
414
  return {};
412
415
  });
413
- const emptyProfileMessage = computed(() => {
414
- if (isCurrentUser.value) {
415
- return t("You have not added any info yet");
416
- }
417
- const name = profileData.value?.displayname || props.user || "";
418
- return t("{user} has not added any info yet", { user: name });
419
- });
420
416
  const avatarUserStatus = computed(() => ({
421
417
  status: userStatus.value.status ?? null,
422
418
  icon: userStatus.value.icon ?? null,
@@ -473,6 +469,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
473
469
  watch(() => props.profile, (value) => {
474
470
  if (value) {
475
471
  profileData.value = value;
472
+ profileEnabled.value = true;
476
473
  if (props.user) {
477
474
  setCachedProfile(props.user, value);
478
475
  }
@@ -482,11 +479,19 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
482
479
  watch(() => props.preloadedUserStatus, (value) => {
483
480
  if (value) {
484
481
  userStatus.value = value;
482
+ userStatusReady.value = true;
483
+ }
484
+ });
485
+ watch(() => props.displayName, (value) => {
486
+ if (value && profileData.value && !profileEnabled.value) {
487
+ profileData.value = { ...profileData.value, displayname: value };
485
488
  }
486
489
  });
487
490
  watch(() => props.user, () => {
488
491
  profileData.value = props.profile;
489
492
  userStatus.value = props.preloadedUserStatus ?? {};
493
+ userStatusReady.value = props.preloadedUserStatus !== null;
494
+ profileEnabled.value = !!props.profile;
490
495
  error.value = false;
491
496
  if (props.user && props.profile) {
492
497
  setCachedProfile(props.user, props.profile);
@@ -505,12 +510,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
505
510
  loadProfile();
506
511
  }
507
512
  });
508
- function hasPreloadedUserStatus() {
509
- return props.preloadedUserStatus !== null || !!(userStatus.value.icon || userStatus.value.message || userStatus.value.status);
513
+ async function resolveDisplayName(userId) {
514
+ if (props.displayName) {
515
+ return props.displayName;
516
+ }
517
+ try {
518
+ const { data } = await axios.post(generateUrl("/displaynames"), { users: [userId] });
519
+ return data?.users?.[userId] || userId;
520
+ } catch (e) {
521
+ logger.debug("Failed to load display name for hovercard", { error: e, userId });
522
+ return userId;
523
+ }
524
+ }
525
+ async function createLimitedProfile(userId) {
526
+ return {
527
+ userId,
528
+ displayname: await resolveDisplayName(userId),
529
+ actions: [],
530
+ isUserAvatarVisible: true
531
+ };
510
532
  }
511
533
  async function ensureUserStatus(userId) {
512
- if (!hasPreloadedUserStatus()) {
534
+ if (!userStatusReady.value) {
513
535
  userStatus.value = await fetchUserStatus(userId);
536
+ userStatusReady.value = true;
514
537
  }
515
538
  }
516
539
  async function loadProfile() {
@@ -522,30 +545,43 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
522
545
  const cached = getCachedProfile(userId);
523
546
  if (cached) {
524
547
  profileData.value = cached;
548
+ profileEnabled.value = true;
525
549
  }
526
550
  }
527
- if (profileData.value) {
528
- await ensureUserStatus(userId);
551
+ if (profileData.value && profileEnabled.value) {
552
+ if (!userStatusReady.value) {
553
+ loading.value = true;
554
+ try {
555
+ await ensureUserStatus(userId);
556
+ } finally {
557
+ loading.value = false;
558
+ }
559
+ }
529
560
  return;
530
561
  }
531
562
  loading.value = true;
532
563
  error.value = false;
564
+ const statusPromise = userStatusReady.value ? Promise.resolve(userStatus.value) : fetchUserStatus(userId);
533
565
  try {
534
- const [profile, status] = await Promise.all([
535
- fetchProfileCached(userId, async () => {
536
- const { data } = await axios.get(generateOcsUrl("/profile/{userId}", { userId }));
537
- return data.ocs?.data ?? null;
538
- }),
539
- hasPreloadedUserStatus() ? Promise.resolve(userStatus.value) : fetchUserStatus(userId)
540
- ]);
541
- profileData.value = profile;
542
- userStatus.value = status;
543
- if (!profileData.value) {
544
- error.value = true;
566
+ const profile = await fetchProfileCached(userId, async () => {
567
+ const { data } = await axios.get(generateOcsUrl("/profile/{userId}", { userId }));
568
+ return data.ocs?.data ?? null;
569
+ });
570
+ if (profile) {
571
+ profileData.value = profile;
572
+ profileEnabled.value = true;
573
+ } else {
574
+ profileData.value = await createLimitedProfile(userId);
575
+ profileEnabled.value = false;
545
576
  }
546
577
  } catch (e) {
547
- logger.debug("Failed to load profile for hovercard", { error: e, user: userId });
548
- error.value = true;
578
+ logger.debug("Failed to load profile for hovercard, showing limited info", { error: e, user: userId });
579
+ profileData.value = await createLimitedProfile(userId);
580
+ profileEnabled.value = false;
581
+ }
582
+ try {
583
+ userStatus.value = await statusPromise;
584
+ userStatusReady.value = true;
549
585
  } finally {
550
586
  loading.value = false;
551
587
  }
@@ -564,11 +600,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
564
600
  }
565
601
  return (_ctx, _cache) => {
566
602
  return openBlock(), createElementBlock("div", {
567
- class: "profile-hover-card",
603
+ class: normalizeClass(["profile-hover-card", { "profile-hover-card--limited": !showLoading.value && !!profileData.value && !error.value && !profileEnabled.value }]),
568
604
  role: "dialog",
569
- "aria-label": unref(t)("Profile of {user}", { user: profileData.value?.displayname || __props.user || "" })
605
+ "aria-label": unref(t)("Profile of {user}", { user: resolvedDisplayName.value })
570
606
  }, [
571
- loading.value ? (openBlock(), createElementBlock("div", _hoisted_2, [
607
+ showLoading.value ? (openBlock(), createElementBlock("div", _hoisted_2, [
572
608
  createVNode(NcLoadingIcon, {
573
609
  size: 32,
574
610
  name: unref(t)("Loading profile")
@@ -590,45 +626,67 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
590
626
  _: 1
591
627
  }, 8, ["aria-label", "title", "href"])) : createCommentVNode("", true),
592
628
  createElementVNode("div", _hoisted_4, [
593
- unref(isMobile) ? (openBlock(), createBlock(NcAvatar, {
629
+ unref(isMobile) ? (openBlock(), createBlock(resolveDynamicComponent(profileUrl.value ? "a" : "div"), mergeProps({
594
630
  key: 0,
595
- class: "avatar profile-hover-card__header__container__avatar",
596
- user: profileData.value.userId,
597
- size: 96,
598
- disableMenu: "",
599
- disableTooltip: "",
600
- preloadedUserStatus: avatarUserStatus.value,
601
- isNoUser: !profileData.value.isUserAvatarVisible
602
- }, null, 8, ["user", "preloadedUserStatus", "isNoUser"])) : (openBlock(), createElementBlock("div", _hoisted_5)),
631
+ class: ["profile-hover-card__header__container__avatar", { "profile-hover-card__profile-link": !!profileUrl.value }]
632
+ }, profileLinkProps.value), {
633
+ default: withCtx(() => [
634
+ createVNode(NcAvatar, {
635
+ class: "avatar",
636
+ user: profileData.value.userId,
637
+ displayName: resolvedDisplayName.value,
638
+ size: 96,
639
+ disableMenu: "",
640
+ disableTooltip: "",
641
+ preloadedUserStatus: avatarUserStatus.value,
642
+ isNoUser: !profileData.value.isUserAvatarVisible
643
+ }, null, 8, ["user", "displayName", "preloadedUserStatus", "isNoUser"])
644
+ ]),
645
+ _: 1
646
+ }, 16, ["class"])) : (openBlock(), createElementBlock("div", _hoisted_5)),
603
647
  createElementVNode("div", _hoisted_6, [
604
648
  createElementVNode("div", _hoisted_7, [
605
- createElementVNode("h2", null, toDisplayString(profileData.value.displayname || profileData.value.userId), 1),
606
- profileData.value.pronouns ? (openBlock(), createElementBlock("span", _hoisted_8, "·")) : createCommentVNode("", true),
607
- profileData.value.pronouns ? (openBlock(), createElementBlock("span", _hoisted_9, toDisplayString(profileData.value.pronouns), 1)) : createCommentVNode("", true)
649
+ profileUrl.value ? (openBlock(), createElementBlock("a", {
650
+ key: 0,
651
+ class: "profile-hover-card__profile-link",
652
+ href: profileUrl.value
653
+ }, [
654
+ createElementVNode("h2", null, toDisplayString(resolvedDisplayName.value), 1)
655
+ ], 8, _hoisted_8)) : (openBlock(), createElementBlock("h2", _hoisted_9, toDisplayString(resolvedDisplayName.value), 1)),
656
+ profileData.value.pronouns ? (openBlock(), createElementBlock("span", _hoisted_10, "·")) : createCommentVNode("", true),
657
+ profileData.value.pronouns ? (openBlock(), createElementBlock("span", _hoisted_11, toDisplayString(profileData.value.pronouns), 1)) : createCommentVNode("", true)
608
658
  ]),
609
- userStatus.value.icon || userStatus.value.message ? (openBlock(), createElementBlock("div", _hoisted_10, [
610
- createElementVNode("span", _hoisted_11, [
659
+ userStatus.value.icon || userStatus.value.message ? (openBlock(), createElementBlock("div", _hoisted_12, [
660
+ createElementVNode("span", _hoisted_13, [
611
661
  createElementVNode("span", null, toDisplayString(userStatus.value.icon) + " " + toDisplayString(userStatus.value.message), 1)
612
662
  ])
613
663
  ])) : createCommentVNode("", true)
614
664
  ])
615
665
  ])
616
666
  ]),
617
- createElementVNode("div", _hoisted_12, [
618
- createElementVNode("div", _hoisted_13, [
619
- createElementVNode("div", _hoisted_14, [
620
- !unref(isMobile) ? (openBlock(), createBlock(NcAvatar, {
667
+ createElementVNode("div", _hoisted_14, [
668
+ createElementVNode("div", _hoisted_15, [
669
+ createElementVNode("div", _hoisted_16, [
670
+ !unref(isMobile) ? (openBlock(), createBlock(resolveDynamicComponent(profileUrl.value ? "a" : "div"), mergeProps({
621
671
  key: 0,
622
- class: "avatar",
623
- user: profileData.value.userId,
624
- size: 135,
625
- disableMenu: "",
626
- disableTooltip: "",
627
- preloadedUserStatus: avatarUserStatus.value,
628
- isNoUser: !profileData.value.isUserAvatarVisible
629
- }, null, 8, ["user", "preloadedUserStatus", "isNoUser"])) : createCommentVNode("", true),
630
- createElementVNode("div", _hoisted_15, [
631
- __props.actionsLoading && resolvedActions.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_16, [
672
+ class: { "profile-hover-card__profile-link": !!profileUrl.value }
673
+ }, profileLinkProps.value), {
674
+ default: withCtx(() => [
675
+ createVNode(NcAvatar, {
676
+ class: "avatar",
677
+ user: profileData.value.userId,
678
+ displayName: resolvedDisplayName.value,
679
+ size: 135,
680
+ disableMenu: "",
681
+ disableTooltip: "",
682
+ preloadedUserStatus: avatarUserStatus.value,
683
+ isNoUser: !profileData.value.isUserAvatarVisible
684
+ }, null, 8, ["user", "displayName", "preloadedUserStatus", "isNoUser"])
685
+ ]),
686
+ _: 1
687
+ }, 16, ["class"])) : createCommentVNode("", true),
688
+ createElementVNode("div", _hoisted_17, [
689
+ __props.actionsLoading && resolvedActions.value.length === 0 ? (openBlock(), createElementBlock("div", _hoisted_18, [
632
690
  createVNode(NcLoadingIcon, {
633
691
  size: 20,
634
692
  name: unref(t)("Loading actions")
@@ -642,7 +700,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
642
700
  onClick: primaryAction.value.onClick
643
701
  }), createSlots({
644
702
  default: withCtx(() => [
645
- createTextVNode(" " + toDisplayString(primaryAction.value.text), 1)
703
+ createTextVNode(" " + toDisplayString(actionDisplayText(primaryAction.value)), 1)
646
704
  ]),
647
705
  _: 2
648
706
  }, [
@@ -657,7 +715,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
657
715
  src: primaryAction.value.icon,
658
716
  alt: "",
659
717
  class: "user-actions__primary__icon"
660
- }, null, 8, _hoisted_17)) : (openBlock(), createElementBlock("span", {
718
+ }, null, 8, _hoisted_19)) : (openBlock(), createElementBlock("span", {
661
719
  key: 2,
662
720
  "aria-hidden": "true",
663
721
  class: normalizeClass(["user-actions__primary__icon-class", primaryAction.value.icon])
@@ -677,7 +735,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
677
735
  key: action.id || action.href || index
678
736
  }, { ref_for: true }, otherActionProps(action)), createSlots({
679
737
  default: withCtx(() => [
680
- createTextVNode(" " + toDisplayString(action.text), 1)
738
+ createTextVNode(" " + toDisplayString(actionDisplayText(action)), 1)
681
739
  ]),
682
740
  _: 2
683
741
  }, [
@@ -692,7 +750,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
692
750
  src: action.icon,
693
751
  alt: "",
694
752
  class: "user-actions__other__icon"
695
- }, null, 8, _hoisted_18)) : (openBlock(), createElementBlock("span", {
753
+ }, null, 8, _hoisted_20)) : (openBlock(), createElementBlock("span", {
696
754
  key: 2,
697
755
  "aria-hidden": "true",
698
756
  class: normalizeClass(["user-actions__other__icon-class", action.icon])
@@ -708,9 +766,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
708
766
  ], 64))
709
767
  ])
710
768
  ]),
711
- createElementVNode("div", _hoisted_19, [
712
- profileData.value.organisation || profileData.value.role || profileData.value.address || localTimeLabel.value ? (openBlock(), createElementBlock("div", _hoisted_20, [
713
- profileData.value.organisation || profileData.value.role ? (openBlock(), createElementBlock("div", _hoisted_21, [
769
+ profileEnabled.value ? (openBlock(), createElementBlock("div", _hoisted_21, [
770
+ profileData.value.organisation || profileData.value.role || profileData.value.address || localTimeLabel.value ? (openBlock(), createElementBlock("div", _hoisted_22, [
771
+ profileData.value.organisation || profileData.value.role ? (openBlock(), createElementBlock("div", _hoisted_23, [
714
772
  createElementVNode("p", null, [
715
773
  createVNode(BriefcaseIcon, {
716
774
  class: "detail-icon",
@@ -718,11 +776,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
718
776
  title: ""
719
777
  }),
720
778
  createTextVNode(" " + toDisplayString(profileData.value.organisation) + " ", 1),
721
- profileData.value.organisation && profileData.value.role ? (openBlock(), createElementBlock("span", _hoisted_22, "•")) : createCommentVNode("", true),
779
+ profileData.value.organisation && profileData.value.role ? (openBlock(), createElementBlock("span", _hoisted_24, "•")) : createCommentVNode("", true),
722
780
  createTextVNode(" " + toDisplayString(profileData.value.role), 1)
723
781
  ])
724
782
  ])) : createCommentVNode("", true),
725
- profileData.value.address ? (openBlock(), createElementBlock("div", _hoisted_23, [
783
+ profileData.value.address ? (openBlock(), createElementBlock("div", _hoisted_25, [
726
784
  createElementVNode("p", null, [
727
785
  createVNode(MapMarkerIcon, {
728
786
  class: "detail-icon",
@@ -732,7 +790,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
732
790
  createTextVNode(" " + toDisplayString(profileData.value.address), 1)
733
791
  ])
734
792
  ])) : createCommentVNode("", true),
735
- localTimeLabel.value ? (openBlock(), createElementBlock("div", _hoisted_24, [
793
+ localTimeLabel.value ? (openBlock(), createElementBlock("div", _hoisted_26, [
736
794
  createElementVNode("p", null, [
737
795
  createVNode(ClockIcon, {
738
796
  class: "detail-icon",
@@ -744,33 +802,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
744
802
  ])) : createCommentVNode("", true)
745
803
  ])) : createCommentVNode("", true),
746
804
  profileData.value.headline || profileData.value.biography ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
747
- profileData.value.headline ? (openBlock(), createElementBlock("h3", _hoisted_25, toDisplayString(profileData.value.headline), 1)) : createCommentVNode("", true),
748
- profileData.value.biography ? (openBlock(), createElementBlock("div", _hoisted_26, [
805
+ profileData.value.headline ? (openBlock(), createElementBlock("h3", _hoisted_27, toDisplayString(profileData.value.headline), 1)) : createCommentVNode("", true),
806
+ profileData.value.biography ? (openBlock(), createElementBlock("div", _hoisted_28, [
749
807
  createVNode(NcRichText, {
750
808
  text: profileData.value.biography,
751
809
  useExtendedMarkdown: ""
752
810
  }, null, 8, ["text"])
753
811
  ])) : createCommentVNode("", true)
754
- ], 64)) : (openBlock(), createBlock(NcEmptyContent, {
755
- key: 2,
756
- class: "profile-hover-card__blocks-empty-info",
757
- name: emptyProfileMessage.value,
758
- description: unref(t)("The headline and about sections will show up here")
759
- }, {
760
- icon: withCtx(() => [
761
- createVNode(AccountIcon, { size: 40 })
762
- ]),
763
- _: 1
764
- }, 8, ["name", "description"]))
765
- ])
812
+ ], 64)) : createCommentVNode("", true)
813
+ ])) : createCommentVNode("", true)
766
814
  ])
767
815
  ])
768
- ], 64)) : (openBlock(), createElementBlock("div", _hoisted_27, toDisplayString(unref(t)("Failed to load profile")), 1))
769
- ], 8, _hoisted_1);
816
+ ], 64)) : createCommentVNode("", true)
817
+ ], 10, _hoisted_1);
770
818
  };
771
819
  }
772
820
  });
773
- const NcProfileHoverCard = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-dc040af1"]]);
821
+ const NcProfileHoverCard = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-592f6ec3"]]);
774
822
  export {
775
823
  NcProfileHoverCard as default
776
824
  };