is_active = ! $channel->is_active; $channel->save(); } public function openCreateModal(): void { $this->reset(['newName', 'newPlatformInstanceId', 'newLanguageId', 'newDescription']); $this->resetErrorBag(); $this->showCreateModal = true; } public function closeCreateModal(): void { $this->showCreateModal = false; } public function createChannel(CreateChannelAction $action): void { $this->validate([ // name doubles as the Lemmy community slug (used verbatim as channel_id for // community lookup at publish time), so it must be lowercase slug format. 'newName' => [ 'required', 'string', 'max:255', 'regex:/^[a-z0-9_]+$/', Rule::unique('platform_channels', 'name') ->where('platform_instance_id', $this->newPlatformInstanceId), ], 'newPlatformInstanceId' => 'required|integer|exists:platform_instances,id', 'newLanguageId' => 'nullable|integer|exists:languages,id', ], [ 'newName.regex' => 'The name must be a valid community slug (lowercase letters, numbers, and underscores only).', 'newName.unique' => 'A channel with this name already exists for this instance.', ]); try { $action->execute( $this->newName, $this->newPlatformInstanceId, $this->newLanguageId, // Blade textarea binds an empty string when blank; the action expects null for "no description". $this->newDescription !== '' ? $this->newDescription : null, ); } catch (UniqueConstraintViolationException $e) { // Unreachable via this form (the unique rule above catches duplicates first), // but the (platform_instance_id, channel_id) index can still fire if channel_id // ever drifts from name. Surface it as a field error instead of a 500. $this->addError('newName', 'A channel with this name already exists for this instance.'); return; } catch (RuntimeException $e) { $this->addError('newPlatformInstanceId', $e->getMessage()); return; } $this->closeCreateModal(); } public function openAccountModal(int $channelId): void { $this->managingChannelId = $channelId; } public function closeAccountModal(): void { $this->managingChannelId = null; } public function attachAccount(int $accountId): void { if (! $this->managingChannelId) { return; } $channel = PlatformChannel::findOrFail($this->managingChannelId); if (! $channel->platformAccounts()->where('platform_account_id', $accountId)->exists()) { $channel->platformAccounts()->attach($accountId, [ 'is_active' => true, 'priority' => 1, 'created_at' => now(), 'updated_at' => now(), ]); } } public function detachAccount(int $channelId, int $accountId): void { $channel = PlatformChannel::findOrFail($channelId); $channel->platformAccounts()->detach($accountId); } public function render(): View { $channels = PlatformChannel::with(['platformInstance', 'platformAccounts'])->orderBy('name')->get(); $allAccounts = PlatformAccount::where('is_active', true)->get(); $managingChannel = $this->managingChannelId ? PlatformChannel::with('platformAccounts')->find($this->managingChannelId) : null; $availableAccounts = $managingChannel ? $allAccounts->filter(fn ($account) => ! $managingChannel->platformAccounts->contains('id', $account->id)) : collect(); return view('livewire.channels', [ 'channels' => $channels, 'managingChannel' => $managingChannel, 'availableAccounts' => $availableAccounts, 'platformInstances' => PlatformInstance::where('is_active', true)->orderBy('name')->get(), 'languages' => Language::where('is_active', true)->orderBy('name')->get(), ])->layout('layouts.app'); } }