Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/core/src/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export type PropertyType = any
export interface UXObject extends Obj {
label: IntlString
icon?: Asset
color?: number
hidden?: boolean
readonly?: boolean
}
Expand Down
22 changes: 20 additions & 2 deletions packages/presentation/src/components/IconWithEmoji.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

export let icon: number | number[] | Ref<Blob>
export let size: IconSize
export let inline: boolean = false

let value: string | undefined = parseIcon(icon)

Expand All @@ -39,15 +40,15 @@
$: value = parseIcon(icon)
</script>

<div class="emoji-{size} flex-row-center emoji">
<span class="emoji-{size} flex-row-center emoji" class:inline class:fitSize={inline}>
{#if value !== undefined}
{value}
{:else}
{#await getBlobRef(asRef(icon)) then iconBlob}
<img src={iconBlob.src} srcset={iconBlob.srcset} alt="icon" />
{/await}
{/if}
</div>
</span>

<style lang="scss">
.emoji {
Expand All @@ -59,6 +60,15 @@
img {
margin: 0;
}

&.inline {
display: inline;

img {
margin-bottom: -0.125rem;
vertical-align: unset;
}
}
}
.emoji-inline {
width: 1em;
Expand All @@ -70,6 +80,13 @@
height: 0.75rem;
font-size: 0.75rem;
}

.emoji-smaller {
width: 0.875rem;
height: 0.875rem;
font-size: 0.875rem;
}

.emoji-small {
width: 1rem;
height: 1rem;
Expand All @@ -89,6 +106,7 @@
width: inherit;
height: inherit;
}
.emoji-smaller,
.emoji-x-small,
.emoji-small,
.emoji-medium,
Expand Down
13 changes: 10 additions & 3 deletions packages/presentation/src/components/markup/ObjectNode.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import { createQuery, getClient } from '../../utils'
import MessageBox from '../MessageBox.svelte'
import presentation from '../../plugin'
import { IconWithEmoji } from '../../index'

export let _id: Ref<Doc> | undefined = undefined
export let _class: Ref<Class<Doc>> | undefined = undefined
Expand All @@ -35,12 +36,14 @@
let broken: boolean = false
const withoutDoc: Ref<Doc>[] = [contact.mention.Here, contact.mention.Everyone]

$: clazz = _class ? hierarchy.findClass(_class) : undefined

$: icon =
_class !== undefined &&
hierarchy.hasClass(_class) &&
!withoutDoc.includes(_id as any) &&
!hierarchy.isDerived(_class, contact.class.Contact)
? hierarchy.getClass(_class).icon
? clazz?.icon
: null

$: if (_class != null && _id != null && hierarchy.hasClass(_class) && !withoutDoc.includes(_id as any)) {
Expand All @@ -64,8 +67,12 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<span class="antiMention" class:transparent class:broken on:click={onBrokenLinkClick}>
{#if icon}<Icon {icon} size="small" />{' '}{:else}@{/if}{#if _id === contact.mention.Here}<span class="lower"
><Label label={contact.string.Here} /></span
{#if icon}{#if icon === view.ids.IconWithEmoji}<IconWithEmoji
icon={clazz?.color ?? 0}
size={'smaller'}
inline
/>{:else}<Icon {icon} size="small" />{/if}{' '}{:else}@{/if}{#if _id === contact.mention.Here}<span
class="lower"><Label label={contact.string.Here} /></span
>{:else if _id === contact.mention.Everyone}<span class="lower"><Label label={contact.string.Everyone} /></span
>{:else}{title}{/if}
</span>
Expand Down
2 changes: 1 addition & 1 deletion packages/theme/styles/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,7 @@

&.transparent {
background-color: transparent;

&:hover {
background-color: transparent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
-->
<script lang="ts">
import { getClient } from '@hcengineering/presentation'
import { type Card } from '@hcengineering/card'
import cardPlugin, { type Card } from '@hcengineering/card'
import { type ActivityMessage } from '@hcengineering/communication-types'
import view from '@hcengineering/view'
import { DocNavLink } from '@hcengineering/view-resources'
import { DocNavLink, ObjectIcon } from '@hcengineering/view-resources'
import { Icon, Label } from '@hcengineering/ui'

import communication from './../../../plugin'
Expand All @@ -34,11 +34,13 @@
</script>

<span class="container flex-gap-1 overflow-label">
{#if clazz.icon}
<span class="icon mr-1">
<Icon icon={clazz.icon} size="small" />
</span>
{/if}
<span class="icon mr-1">
{#if hierarchy.isDerived(card._class, communication.type.Direct)}
<Icon icon={clazz.icon ?? cardPlugin.icon.Card} size="small" />
{:else}
<ObjectIcon value={card} size={'small'} />
{/if}
</span>

{#if action === 'create'}
<Label label={communication.string.New} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import { SvelteRenderer } from '../node-view'
import { ReferenceNode, type ReferenceNodeProps, type ReferenceOptions } from '@hcengineering/text'
import Suggestion, { type SuggestionKeyDownProps, type SuggestionOptions, type SuggestionProps } from './suggestion'

import { type Class, type Doc, type Ref } from '@hcengineering/core'
import { type Blob, type Class, type Doc, type Ref } from '@hcengineering/core'
import { getMetadata, getResource, translate } from '@hcengineering/platform'
import presentation, { createQuery, getClient, MessageBox } from '@hcengineering/presentation'
import presentation, { createQuery, getBlobRef, getClient, MessageBox } from '@hcengineering/presentation'
import view from '@hcengineering/view'

import contact from '@hcengineering/contact'
import { parseLocation, showPopup, tooltip, type LabelAndProps, type Location } from '@hcengineering/ui'
import { parseLocation, showPopup, tooltip, type LabelAndProps, type Location, fromCodePoint } from '@hcengineering/ui'
import workbench, { type Application } from '@hcengineering/workbench'

export interface ReferenceExtensionOptions extends ReferenceOptions {
Expand Down Expand Up @@ -145,7 +145,7 @@ export const ReferenceExtension = ReferenceNode.extend<ReferenceExtensionOptions
titleSpan.innerText = `${iconUrl !== '' ? '' : options.suggestion.char}${trans}`
root.classList.add('lower')
} else {
titleSpan.innerText = `${iconUrl !== '' ? '' : options.suggestion.char}${props.label ?? props.id}`
titleSpan.innerText = `${iconUrl !== '' || emojiCode != null ? '' : options.suggestion.char}${props.label ?? props.id}`
}
if (broken) {
root.classList.add('broken')
Expand All @@ -156,10 +156,17 @@ export const ReferenceExtension = ReferenceNode.extend<ReferenceExtensionOptions

const icon =
objectclass !== undefined && !hierarchy.isDerived(objectclass, contact.class.Contact)
? hierarchy.getClass(objectclass).icon
? hierarchy.findClass(objectclass)?.icon
: undefined

const iconUrl = typeof icon === 'string' ? getMetadata(icon) ?? 'https://anticrm.org/logo.svg' : ''
let iconUrl = ''
let emojiCode: number | undefined

if (icon === view.ids.IconWithEmoji) {
emojiCode = hierarchy.findClass(objectclass)?.color ?? 0
} else if (typeof icon === 'string') {
iconUrl = getMetadata(icon) ?? 'https://anticrm.org/logo.svg'
}

if (iconUrl !== '') {
const svg = root.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
Expand All @@ -168,6 +175,10 @@ export const ReferenceExtension = ReferenceNode.extend<ReferenceExtensionOptions
svg.setAttribute('fill', 'currentColor')
const use = svg.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'use'))
use.setAttributeNS('http://www.w3.org/1999/xlink', 'href', iconUrl)
} else if (emojiCode !== undefined) {
const emojiEl = createEmojiElement(emojiCode)
root.appendChild(emojiEl)
root.appendChild(document.createTextNode(' '))
}

let tooltipHandle: any
Expand Down Expand Up @@ -575,3 +586,49 @@ function makeQuery (obj: Record<string, string | number | boolean | null | undef
})
.join('&')
}

function parseEmoji (icon: number | number[] | Ref<Blob>): string | undefined {
if (typeof icon === 'object' && '__ref' in icon) {
return undefined
}
try {
return Array.isArray(icon) ? fromCodePoint(...icon) : fromCodePoint(icon as number)
} catch (err) {}
return undefined
}

function createEmojiElement (emojiCode: number | number[] | Ref<Blob>): HTMLElement {
const root = document.createElement('span')
Object.assign(root.style, {
display: 'inline',
flexShrink: '0',
color: 'black'
})

const value = parseEmoji(emojiCode as any)
if (value !== undefined) {
root.textContent = value
return root
}

const placeholder = document.createElement('span')
placeholder.textContent = '@'
root.appendChild(placeholder)

void getBlobRef(emojiCode as Ref<Blob>).then((iconBlob) => {
if (!root.isConnected) return

const img = document.createElement('img')
img.alt = 'icon'
img.src = iconBlob.src
if (iconBlob.srcset != null) img.srcset = iconBlob.srcset
img.style.display = 'inline'
img.style.margin = '0'
img.style.maxHeight = '0.875rem'
img.style.marginBottom = '-0.125rem'
img.style.verticalAlign = 'unset'
root.replaceChild(img, placeholder)
})

return root
}
10 changes: 8 additions & 2 deletions plugins/view-resources/src/components/ObjectMention.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<script lang="ts">
import { Class, Doc, Ref } from '@hcengineering/core'
import { getResource, translateCB } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { createQuery, getClient, IconWithEmoji } from '@hcengineering/presentation'
import { AnyComponent, Icon, LabelAndProps, themeStore, tooltip } from '@hcengineering/ui'
import view from '@hcengineering/view'

Expand Down Expand Up @@ -60,6 +60,8 @@
doc = object
}

$: cl = doc?._class ?? _class
$: clazz = cl ? hierarchy.findClass(cl) : undefined
$: icon =
doc !== undefined && !hierarchy.isDerived(doc._class, contact.class.Contact) ? classIcon(client, doc._class) : null

Expand Down Expand Up @@ -126,7 +128,11 @@
use:tooltip={docTooltip}
>
<DocNavLink object={doc} component={docComponent} {disabled} inlineReference {onClick} {transparent}>
{#if icon}<Icon {icon} size="small" />{' '}{:else}@{/if}{displayTitle}
{#if icon}{#if icon === view.ids.IconWithEmoji}<IconWithEmoji
icon={clazz?.color ?? 0}
size={'smaller'}
inline
/>{:else}<Icon {icon} size="small" />{/if}{' '}{:else}@{/if}{displayTitle}
</DocNavLink>
</span>
{/if}
Loading