The onExternalClick custom hook keeps a reference to elements that may
no longer be in the DOM, this can cause entire sections of the DOM that
are no longer needed to be kept in memory, and can also retain the
associated Owl components and their data.
To solve this, we set the downTarget and upTarget to null after calling
the callback. In practice they are no longer used in the code but we are
keeping it for stable compatibility.
closesodoo/odoo#153654
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Access `proxy[key]` only once to avoid triggering reactive `get()` many
times, as this will be triggered in cascade to all elements in the chain
in internal code, saving possibly dozens of uncessary calls per
callback.
Part-of: odoo/odoo#147814
Since [1], the test that ensures live chat threads are sorted
according to their last interrest date is broken. Indeed, the sort was
moved from `im_livechat` to `website_livechat`. This is incorrect.
Also, most of the compare functions used to sort by datetime were
incorrect: those datetimes can be undefined in which case the result
of the compare function would be `NaN`.
This PR moves back the sort function in the correct module and
introduce a standard way to compare by datetime which handles
undefined datetimes correctly.
[1]: https://github.com/odoo/odoo/pull/143382
fixes runbot-47784
closesodoo/odoo#146805
Related: odoo/enterprise#53065
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
See comment in diff for rationale about the `isLoaded` change.
Also highlighting message before jumping to present can conflict: some
programatic scroll changes are prevented or delayed while there is a
highlight, jumping to present should clear that.
All "previous state" variables need to be reset when re-using the thread
component after making a change that led to reloading the message list
(such as a long jump). They are used to compare value before/after some
changes, but when jumping, the state should be considered clean.
`isJumpingRecent` is obsolete heuristics that has been replaced by
better controlling scroll and visibility check.
Extra `await` in `loadAround` makes no sense.
It's the best guess to fix the following runbot issues. The error
doesn't happen frequently enough to be a guaranteed fix.
runbot-40592
runbot-48557
closesodoo/odoo#145419
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
The IntersectionObserver was sometimes started and called its callback
before the scroll was restored, in which case the load more button was
always visible, leading to loading more messages than intended.
To fix, delay the starting of the visible until the scroll is restored.
runbot-35533
closesodoo/odoo#144228
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
The issue is that "load older" was called every time the thread was made
visible, in particular after chat window unfold.
The load more button will naturally be visible when first loading a
thread, it only makes sense to check its final visibility and not
intermediate steps.
But there was a bug where the loading mechanism was relying on the
initial "load older" to fetch messages, because the messaging menu
preview was incorrectly setting the thread as already loaded, when it
just fetched the last message.
Moreover, the "last message" displayed in the preview was not correctly
computed, and it could end up being the last "currently fetched" message
and not the last of all messages (when jumping in the past), and it
could also be a non-persistent message.
runbot-35533
closesodoo/odoo#143129
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Completely rewrite the 3 scroll hooks into a unified version that
doesn't have conflicting and overriding conditions.
- re-apply scroll (bottom in particular) when images are loaded
- restore auto-scrolling to newly posted message
- don't do any scroll save/restore before the thread is loaded
- don't snapshot before the thread is loaded
- don't snapshot after patch
- fix condition for detecting when to restore snapshot
- don't apply scroll multiple times for highlight
Follow up of https://github.com/odoo/odoo/pull/141999/
Only breaking after https://github.com/odoo/odoo/pull/136539
Also follow-up fix of https://github.com/odoo/odoo/pull/127889/
runbot-39172
closesodoo/odoo#142308
Related: odoo/enterprise#50931
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Before this commit, the Messaging Menu had the following issues:
- Header is too large;
- Header color in dark theme is too white;
- Important notifications (= needactions) are not highlighted enough
compared to muted notifications;
- Notification body and title looked too alike;
=> title should be more visible than content
- Mouse-hovering on notification items breaks background-inherit
style of avatar and IM status;
=> side-effect of `list-group-item-action`
- Desktop: Header items slightly move when changing selection;
=> comes from `fw-bolder`
- Desktop: mark as read button was too small and not visible enough;
- Mobile: too many borders, and they are too strong;
=> undesirable dropdown style
- Mobile: Messaging Menu had poor "New message" button link whereas
Discuss app has nice "Start a conversation" button;
- Mobile: "Start a conversation" button is not shown on livechat tab;
- Mobile: when menu is open while Discuss app is open in background,
it's unclear whether the messaging menu is open or not;
=> missing background highlight on Messaging Menu toggler
- Mobile: State of Mobile Discuss App was not synced properly when
using Messaging Menu at the same time;
=> e.g. unselected tab
- Mobile: Discuss app and Messaging Menu were not properly aligned;
=> Messaging Menu did not offset position based on systray navbar
height
- Mobile: active navbar item was not highlighted enough, especially
in white theme;
- "OdooBot has a suggestion" is shown on all tabs instead of only
in "All" tab like "OdooBot has a request";
This commit fixes all the above issues.
Some styling issues were also affecting the Activity Menu, such as
borders and highlighted open state. This commit applies these
few improvements on the Activity Menu too.
closesodoo/odoo#140405
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
This utils file was added because removing item in JS based on
item content sucks, so some higher-order functions were introduced
to ease it slightly.
As many of its uses has been replaced with `RecordList.delete()`
where data is uniquely linked to a model, in the end the functions
were only used once. These functions have been moved to the only file
that still use them, so that we don't encourage using them.
Part-of: odoo/odoo#139501
This commit reduces the size and avoid conflicts caused by
the embed live chat bundle: jquery, legacy libs...
At the same time, this commit fixes the emoji picker that was
wrongly positionned and scrolled up the page when opening.
Finally, this commit ensures the chat window is always at the
bottom of the screen.
opw-3539362
closesodoo/odoo#139261
X-original-commit: 1b29419e50343bfd723b41368ba38ce63b063d92
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
- Remove "channel" field in thread formatter.
- Pass `type` for all persona formatters.
- Remove some snake_case to camelCase conversions.
- Add support for inverse fields in discuss JS models.
Details:
1. [REF] mail: remove field 'channel' in thread formatter
This field was used for channel-specific fields, which made
sense when there was a dedicated Channel model that was modeled
with composition with Thread.
To simplify formatter of threads, it's best to flatten props
so that channel-specific fields are immediately available on
thread model. This will improve insertion of data with Threads.
This commit also makes the following other changes:
- remove `discuss.channel/legacy_insert` to use
`mail.record/insert` instead.
- Introduce `toData()` on record, which is helpful to have record
in data format e.g. to pass as a JSON.stringifiable object.
2. [REF] mail: slightly simplify Message.insert from notif
The handling of `mail.record/insert` for Message was handling
transition from starred non-empty message to starred empty message.
To simplify all record insert from server formatted data, the notif
data is just inserted in Message. The adjustment of starred counter
is managed at model level.
This is a prerequisite to significantly simplify all
`mail.record/insert` handling.
3. [REF] mail: rename 'res.users.settings' notifications
Before this commit, notifications related to changes of user
settings were using named notification `mail.record/insert`.
This named notification should be only used for Discuss data that
should be inserted in models. `res.users.settings` is not integrated
in Discuss model, thus it has no reason to use this named
notification.
This commit rename the notification name to `res.users.settings` for
these specific notifications. This prepares simplification on
handling any `mail.record/insert` notifications that should simply
call `Record.insert()`
4. [REF] mail: make dedicate notif for Thread/fold_state
This was using named notif "mail.record/insert", which should
be used to immediately insert data in models. This is however
a dedicated notification to imperatively manager chat window
state based on timing of receiving thread data.
This may eventually become a `mail.record/insert` in the future,
but right now it's much simpler to define it as its own named
notification, in preparation to simplify `mail.record/insert`
notifications handling.
5. [REF] mail: remove Channel in mail.record/insert
This is replaced by `Thread`, so that these data can be
immediately inserted in Thread model.
6. [REF] mail: simplify slightly Attachment.update()
Now that data containing commands is supported, we could
just assign with the command rather than destructure and pick
the dict data part.
7. [REF] mail: introduce assignIn() utils
This function helps reduce LOCs from using the "in" conditional
in sequence:
```js
if (a in data) {
this[a] = data[a];
}
if (b in data) {
this[b] = data[b];
}
if (c in data) {
this[c] = data[c];
}
```
To simply:
```js
assignIn(this, data, [a, b, c]);
```
8. [REF] mail: remove snake_case to camelCase conversion in models
They exist for the sake of keeping Python code snake_case and
JS camelCase. While it's good that each language have a community
that prefer syntax convention, when a codebase uses both languages
and they should work with the same data, it's not great to convert
snake_case to camelCase and vice-versa all the time.
Since server has authority over the data, the server chooses the
format for the keys. Most of them are snake_cased, therefore this
is usually the one we pick.
9. [REF] mail: rename Message.messageReactionGroups to Message.reactions
Easier to read, and matches relation name in JS model
10. [REF] mail: remove explicit assign of some many relations in Message
This reduce amount of custom code in insert(), in preparation to make
all models behave the same in response to inserting data.
11. [REF] mail: rename Thread.customName to Thread.channel_custom_name
To match server data field name, and avoid useless conversion in JS.
12. [REF] mail: simplify Message.insert for recipients
Have formatted data contain `type: "partner"` so it can be assigned
in relational field without adding `type: "partner"` manually in JS.
13. [REF] mail: introduce inverse field in discuss models
With this commit, fields in different models can be linked
together, so that one is mirror of the other field.
This simplifies some `onAdd`/`onDelete` that were added to
sync such fields, and this also simplifies insertion in
relational fields for discuss models that are identified
by records, such as the `MessageReactions` that is identified
by the message and the emoji.
14. [REF] mail: rename CannedResponse.name to 'source'
To make JS model and server data more alike.
15. [REF] mail: remove assignDefined in Persona model
So that eventually all model inserts use `Object.assign()`.
16. [REF] mail: remove 'last_message_id' from channel_info
At some point it was used to display last message in messaging menu.
This is already covered by `channel_fetch_preview` when opening the
messaging menu for the 1st time, so passing `last_message_id` in
channel_info is obsolete.
closesodoo/odoo#137750
Related: odoo/enterprise#48484
Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
Before this commit, it was not possible to send messages in
full composer containing user mentions. Even whe the mentions were
added in the small composer and then continuing composing the message
in the full composer.
With this commit, we can now make user and channel mentions in the
full composer, by typing `@` and `#` like in the small composer of
Discuss.
When composing a message in small composer and then switching to full
composer, the mentions are preserved.
task-3470060
closesodoo/odoo#132701
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This PR introduce multiple usage of the escape key:
- Channel selector can now be closed using the escape key
- Using the escape key will focus the composer automatically
Task-3456518
closesodoo/odoo#135031
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
With this commit, instead of `Record.insert()` before setting
relation with records, we can immediately pass record data.
For example:
```js
message.author = { id: 3, type: "partner", name: "Admin" };
thread.messages.add({ id: 10, body: "some-text-content" })
```
This is supported on all relational fields that define a target
model.
To make this work while drastically avoiding cyclic dependencies
in code, whenever data have to be inserted in relation, they are
pre-inserted with essential data, and then they are fully inserted
after being registered in the relation.
closesodoo/odoo#136539
Related: odoo/enterprise#47854
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Relational data in server formatter are:
- for one relation: None/false or object
- for many relations: list of objects or list of commands
The commands were:
- 'insert': to add a new item in a relational field
- 'unlink': to remove an item from a relational field
- 'insert-and-unlink': to remove an item from a relational field
- 'clear': to remove all items from relational field
There was a slight nuance between 'unlink' and 'insert-and-unlink'
at some point, but it becomes irrelevant with current code of model.
The name of the commands were hard to grasp what they actually mean
for the many relations.
This commit improves it by renaming 'insert' by 'ADD' and the 2
'unlink' commands by 'DELETE'. This makes it more apparent that
the data in 'ADD' refers to data of record to add in the relation,
while 'DELETE' refers to data of record to delete from the relation.
The 'clear' has been replaced by `False` value instead of a command.
Part-of: odoo/odoo#136308
- Split d.ts files in `@types` folders that are close to
where the definitions of model & patches.
- Update jsdocs of discuss models to be fully type, including
model patches
When defining a new discuss model or a patch, should define a
`@types/models.d.ts` file. It must make use of module `models`
to define interface with model name:
```ts
declare module "models" {
import { Thread as ThreadClass } from "./thread_model";
export interface Thread extends ThreadClass {}
// necessary to propagate types to relations
export Models {
"Thread": Thread,
}
}
```
When defining a patch, should also define a `@types/models.d.ts`
to augment the interface of the model at hand:
```js
patch(Thread.prototype, {
setup() {
this.pinnedMessages = Record.Set("Messages");
}
});
```
```ts
declare module "models" {
import { Message } from "models";
export interface Thread {
pinnedMessages: Set<Messages>,
}
}
```
Part-of: odoo/odoo#134884
Before this commit, emoji and gif pickers were handled as 2 different
pickers. They had dedicated buttons. This made composer quite
bloated, especially in chat windows were size is narrow.
Also the pickers were always displayed as popover, which is not the
best way to show content in mobile.
This commit improves those pickers in discuss so that only a single
button is present (emoji button). Clicking on this button shows a
picker that groups the emoji and gif picker, both of which can be
selected in the header of the grouped picker.
In mobile, instead of showing a popover, it now shows the grouped
picker below the composer. This makes it show where the soft keyboard
is present in mobile, making it easier to input emojis or gifs on
those devices.
This commit also added slight style changes to both pickers. Notably,
the search bar has an improved style that makes it look good when
next to the composer text input, especially in mobile layout.
task-3015707
closesodoo/odoo#123671
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
1. Introduce `static id` to all models, to uniquely identify
a record in a model. This allows normalizing discuss store
for all models, which helps as preparation for managing
record deletion. Can also be combined
```js
class Message {
static id = "id";
id;
}
class Thread {
static id = AND("model", "id");
}
```
2. Introduce `Model.get()` to easily get a record of model
from data that can identify the record. This prevent leaking
the way the record are stored in `records`, as now all records
are indexed by localId, and localId is technical detail.
```js
Message.get(messageId);
Thread.get({ model: "discuss.channel", id: 1 });
```
Part-of: odoo/odoo#134008
This commit improves the mail `onChange` method by adding
the support for multiple keys. This will make the code shorter
and easier to read.
closesodoo/odoo#133778
Signed-off-by: Didier Debondt (did) <did@odoo.com>
In preparation to clean code of models, e.g. by simplifying model
insertion and reducing side-effects in record insertion.
This commit moves the implementation of the `insert()` in discuss
services to the models, and drop support of the service methods
`insert()`. The only way to insert a model is through the store
entry, e.g. `store.Thread.insert()`.
closesodoo/odoo#133509
Related: odoo/enterprise#46499
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Before this PR, RPC in the search GIFs form could resolve in the wrong order and display outdated result.
This PR introduce the use of useSequential hook witch ensure that irrelevant RPC
are canceled.
closesodoo/odoo#133125
X-original-commit: 39fe84706e02ff7828d5098c9ec56aff274cba64
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Before this commit, discuss models were compared with object
reference, e.g. `thread_1 === thread_2`.
This is unsafe with `owl.reactive()`, because it wraps the objects
in a Proxy, and different proxies may map to a same raw object.
This commit fixes the issue by defining `.eq()` and `.in()` methods
on discuss models, which makes comparison on raw value rather than
proxy/reactive one.
This PR also introduce "not" variants, e.g. `.notEq()`, which eases
readability by having "not" and "eq" next to each other.
These "not" variants must be used without optional chaining,
otherwise this gives the opposite result. For example:
```js
const [t1, t2] = [Thread.insert()];
t1 === t1 // true (OK)
t1.eq(t1) // true (OK)
t1.notEq(t1) // false (OK)
t2?.notEq(t1) // undefined => falsy (notOk)
!t2?.eq(t1) // true (OK)
```
closesodoo/odoo#133065
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Before this PR, if a user copy/past an already encoded url in the composer, the
linkify function would reencode already encoded character.
`%5B%5D` (witch mean `[]`) would become `%255B%255D` because `%` whould be encoded
`%25`.
We start by decoding the url, just in case it's already encoded.
closesodoo/odoo#133010
X-original-commit: 453c91d9c5b0353b5f362ecad487ccfd547856c6
Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
Signed-off-by: Didier Debondt (did) <did@odoo.com>
Before this PR, jumping on a message that is not displayed in it's originThread
would not work.
To reproduce:
* star a message that is a reply.
* open the starred menu.
* Try to jump on the replied message.
This PR fix the issue by not allowing the jump.
closesodoo/odoo#132924
X-original-commit: 914f899f119e4b5f6271613b4af653211a32f915
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This PR cleanup service typing:
* Introduce `addons/mail/tooling/type/services.d.ts` to automatically type
services imported by `useService` hook.
* Correctly type service constructor, setup and start functions.
* Remove now useless `@type`.
* Removing `Object.assign` for services variables.
* Type OdooEnv.services to services.
closesodoo/odoo#131192
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
Before this PR, RPC made by input inside the discuss sidebar could
resolve in the wrong order, witch display outdated results.
This PR ensure that only the most recent RPC is sent to the server,
cancelling irrelevant RPC.
Note: This PR also remove the support for Promise inside the
NavigableList component since it's not compatible with useSequential.
closesodoo/odoo#130767
X-original-commit: ba2d029d876f9acd7c869cc3d345cc4ed7cab00a
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
The `cleanTerm` function was throwing a TypeError ("term.toLowerCase is
not a function") when the email value of a contact was falsy (like
`false`, `null`, or `undefined`), as it was attempting to call
`toLowerCase` on a non-string value.
This was particularly problematic when two contacts had the same name
and at least one of them didn't have an email.
The solution was to make `cleanTerm` consider non-sring values as
empty string, preventing the TypeError when value is `false` from
partner having no email.
opw-3439376
closesodoo/odoo#130233
X-original-commit: 2abdf7a8635ed90f0ad26c6407b21cf3c8c60fcd
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Signed-off-by: Pedram Bi Ria (pebr) <pebr@odoo.com>
Before this commit, the suggestion list would not work when
a string with no match was entered then modified.
Steps to reproduce:
- Open a channel
- Type `/hee` (this string matches no suggestion)
- Delete one of the `e` in order to get `/he`
- This string should match the `/help` suggestion but nothing
is shown.
There is several issues here:
- The suggestion hook is based on the composer selection but
the `selectionChange` event is not triggered when deleting text
from the textarea which leads to incorrect selection.
- The search is cleared in the `suggestionHook` when nothing is
found which leads to incorrect delimiter position after a deletion.
This commit fixes both issues.
closesodoo/odoo#127997
X-original-commit: b8bf65478cad558e02a5902886b3e4272483944e
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Purpose:
This commit adds Emoji_picker functionality to the web_editor,
allowing users to conveniently add emojis to their text and
improving the overall user experience.
Specifications:
Now we can insert emoji in web_editor using `/emoji`.
Task id: 3253958
closesodoo/odoo#125137
Related: odoo/enterprise#42772
Signed-off-by: Simon Genin (ges@odoo) <ges@odoo.com>
This commit adds a GIF picker in discuss
app. GIF feature makes use of Tenor GIF API [1].
To enable GIF picker in discuss, you must provide
a Tenor GIF API key in the General Settings.
Then the GIF picker is visible in all channels
(chat window and discuss app), next to the emoji picker
button.
[1] https://tenor.com/gifapi/documentation
task-2365705
closesodoo/odoo#116060
Related: odoo/enterprise#41959
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Co-authored-by: Brieuc-brd <brd@odoo.com>
Before this commit, chat window actions were all placed in
the right part of header. It was showing the main action (call),
close action, and all other actions in dropdown menu from
the "..." (more) button.
This commit now replaces the "..." (more) button by clicking
on avatar/name of conversation. The "..." (more) button has been
replaced to "_" (minimize/fold) button, as clicking on header to
open/fold chat window can become hard due to avatar + name being
clickable to show most chat window actions.
This commit also adds the following actions in chat window:
- Open (Employee) Profile
- Rename (conversation)
Task-3336752
closesodoo/odoo#124592
Related: odoo/enterprise#42480
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Before this commit, when posting a message in discuss with some
urls, the url was not linkified.
Example of such linkify not working:
```
https://www.45017478-master-all.runbot134.odoo.com/web
```
The url regexp was changed with [1]
to make punctuation mark the end of url to linkify. The 1st dot
removed in diff was a mistake. This commit reverts this part, so
that url above is correctly linkified while fixing the problem
of [1].
[1] https://github.com/odoo/odoo/pull/122621closesodoo/odoo#125081
X-original-commit: bbbc85865b45615937a22ed08b6e560a0aa898a0
Signed-off-by: Stockbauer Matthieu (tsm) <tsm@odoo.com>
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Remove "fake" feature sub-folders that make files harder to find.
Note: If there are too many files in the main folder now, a new split
that actually makes sense can be done at a later time: this would not
just be code move, but removing coupling between said feature and the
rest of the code.
Apply consistent structure, where the top level folder is a feature (or
core), and sub-folders are subdivision of the feature depending on
context (closely related to assets bundles).
```
- core
- common
- public
- web
- feature
- common
- public
- web
```
The opportunity is taken to reorganize the top of the files and imports:
- Always use absolute path in imports to be able to find all usages of a
file with a single search.
- Reorganize imports to group them by module, and to sort them
alphabetically by path/feature.
- Always use single asterisk (*) for `odoo-module`: less characters yay!
And double asterisk should be used for JSDoc comments, not for custom
instructions.
Part of task-3265211
closesodoo/odoo#124168
Related: odoo/enterprise#42121
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>