heyosseus/filum
Real-time chat between admin users inside your Filament panel. Click a colleague, the conversation opens, history persists, and messages arrive as sent. Broadcasting-agnostic and free: uses your broadcaster if configured, otherwise falls back to polling. Dark-first, English and Georgian included.
Model::preventLazyLoading() -- the posture of a careful one -- that is
not a slow thread but a thrown LazyLoadingViolationException, and the chat
would not render at all. Both are eager loaded now, and so is the message and
conversation the attachment download authorises against.tests/TestCase.php forbids lazy loading, so the suite fails on this class of
bug rather than leaving a consumer to find it. It was a consumer that found this
one.filum.attachments configures the disk, the size ceiling, how many files a
message may carry, and the accepted types. The type is read from the file's own
bytes rather than from what the browser claimed, so renaming a script to .png
does not get it past the allowlist.filum.attachments.disk pointed at a private disk.composer update heyosseus/filum
php artisan vendor:publish --tag=filum-migrations-replies
php artisan migrate
Publish only that tag. Publishing filum-migrations on an existing install
copies the earlier migrations a second time under fresh timestamps and migrate
then aborts on the duplicate.
<details> element whose disclosure triangle painted
anyway: display: grid on a summary stops it being a list item, so
list-style: none no longer applies. It rendered as a stray arrow beside the
opener on every message.<details> markup is gone, replaced by Alpine, which Filament already
loads. No new dependency and no build step.Note for anyone styling Filum: the CSS class filum-reaction-pick is now
filum-reaction-add, and the surrounding markup changed. If you published the
views with --tag=filum-views you keep your own copy and will not pick this up;
re-publish with --force or port the change by hand.
filum.reactions.emoji names the set an application offers, and anything
outside it is refused rather than stored. A fixed set rather than a picker is
deliberate: Filum ships compiled CSS and no build step, and a picker would mean
a JavaScript bundle for something a back office uses six of.filum.reactions.enabled switches the feature off; disabled means absent, and
with no emoji in the set every reaction is refused by the same guard that
rejects a typo.composer update heyosseus/filum
php artisan vendor:publish --tag=filum-migrations-reactions
php artisan migrate
Publish only that tag. Publishing filum-migrations on an existing install
copies the earlier migrations a second time under fresh timestamps -- Laravel
looks for the source name and your install has the stamped one -- and migrate
then aborts on the duplicate. Run the tag once; do not put vendor:publish in a
repeatedly-executed deploy step.
filum.groups.enabled switches the whole feature off; disabled means absent.ChatPanel::$conversation is a public Livewire property, so a browser could set
it to any conversation id and every read path — the thread, the group header,
the member count, scrollback, the unread fingerprint — would render whatever it
found. Writes and broadcasts were already gated by membership; reads were not.
Every read path now goes through the same membership check, so a conversation
the viewer has not joined renders nothing, the same as if it did not exist.
filum.groups.enabled promised that a disabled install has no reachable groups,
and for reads and sends that was not true: a joined member could still open a
group by id, read the thread, and send messages that broadcast — while being
unable to leave, because leaving was the one action that checked. The switch is
now enforced at the same read seam as membership, and in Messages::send(), so a
group is genuinely absent while it is off. Nothing is deleted; switching it back
on restores what was there.
Groups::invite() accepted a user id that resolved to nobody, writing a pending
invitation that could never be accepted, never rang, and — with no removal
control — could never be withdrawn. It now refuses one before anything is written.
The bell now rings only for recipients who are not currently present.
Somebody with the panel open already sees the unread count on the colleague, on
the group and on the overlay tab, so a notification as well told them the same
thing twice and accumulated a list to clear. "Present" is the same set the board
shows as HERE NOW, so the two always agree; tune it with presence.ttl.
Applies to invitations too.
Breaking. Notifier gains invited(Conversation $group, Authenticatable $recipient, Authenticatable $inviter): void.
Applications implementing the contract themselves must add it.
Breaking. Conversation::includes() now means joined, not merely present.
This is what keeps a pending invitee out of the thread, the send path and the
broadcast channel. Anything relying on the old meaning changes behaviour.
ChatPanel selects a conversation rather than a user, and board assembly moved
to Heyosseus\Filum\Board\Boards.
composer update heyosseus/filum
php artisan vendor:publish --tag=filum-migrations-groups
php artisan migrate
Publish filum-migrations-groups, not filum-migrations. The broad tag is for
a fresh install only. Laravel stamps a published migration with the moment it was
published, so the copy of create_filum_tables already on your disk is named after
your 0.1.1 install rather than after Filum's source file. vendor:publish looks
for the source name, does not find it, and copies the file again under a fresh
stamp — leaving you with two create-tables migrations. migrate then runs the
duplicate first, hits table already exists, aborts, and never reaches the group
migration. Every schema change after 0.1.1 gets a tag of its own for exactly this
reason.
If you have already done it, delete the newer duplicate of
*_create_filum_tables.php from database/migrations before migrating.
Migrate as part of the deploy, not after it. Between 0.2.0's code going live
and migrate finishing, chat is down — not degraded, down. Conversations::between()
writes kind, state and joined_at, and Conversation::includes() reads
state, so on a schema that lacks those columns every conversation fails,
including the 1:1 ones that worked a moment earlier. Run the migration in the same
release step that ships the code.
Existing direct conversations are unaffected once the migration has run: the new
columns default to direct and joined.
filum.users.guard now defaults to the panel's own guard instead of a hardcoded
web. A panel authenticating its own model against its own guard needed no
configuration to work; with the old default it asked Laravel for the web
guard's model, and where that model does not exist the error surfaced while the
navigation was being built — taking down every page in the panel, not just the
chat. Name a guard explicitly to override.Transport contract with a LaravelBroadcast
driver and a Polling fallback, selected automatically. No paid service is ever
required.filum:install command; publishable config, migrations, translations and views.Compat seam.Notifier contract. One per conversation, on the
transition from caught up to behind, so a burst rings once.The browser never subscribed to the events Filum broadcast, so configuring a
broadcaster switched the poll to its slow reconciliation interval without
putting anything faster in its place — real-time made it slower. The panel now
listens on window.Echo when one is available.
Polling re-rendered the component every few seconds whether or not anything had changed, and each re-render morphed the DOM out from under whoever was typing: the composer lost its contents and its caret. A tick that finds nothing new now renders nothing, and the textarea is left alone by the morph.
Load earlier messages replaced the visible page instead of adding to it, so
the newest messages disappeared when reaching back for context. Scrollback now
only ever grows, and the button appears only when something precedes what is on
screen.
The stylesheet consumed Filament's colour tokens as RGB channel triplets, which
is how Filament 3 published them. Filament 4 and 5 are built on Tailwind 4 and
publish complete colour values, so every declaration holding one was invalid and
silently dropped — the chat rendered with no surfaces, borders, avatars or
buttons. Tokens are now read directly and translucency comes from color-mix.
Migrations published without a date prefix, which sorted them ahead of every application migration and so created the foreign key to the users table before that table existed.
How can I help you explore Laravel packages today?