Follow up to #26712 to account for older threads that don't have a persisted excerpt, as this was previously generated on every page load.
This change allows us to build the excerpt on the fly when none exists, fixing the issue of missing message excerpts for thread previews (within channel) and thread lists (on mobile/desktop).
This would cause an error when deleting the original message of a thread, due to the non existing `last_message`. This fix is implemented using the null pattern.
Note this commit is also using this opportunity to unify naming of null objects, `Chat::DeletedUser` becomes `Chat::NullUser`, it feels better to have a name describing what is the object, instead of a name describing why this object has to be used, which can change depending on cases.