diff --git a/app/Models/PlaylistItem.php b/app/Models/PlaylistItem.php
index d8913fc..e3f3e28 100644
--- a/app/Models/PlaylistItem.php
+++ b/app/Models/PlaylistItem.php
@@ -143,7 +143,13 @@ class PlaylistItem extends Model
}
$pluginMarkups = [];
- $plugins = Plugin::whereIn('id', $this->getMashupPluginIds())->get();
+ $pluginIds = $this->getMashupPluginIds();
+ $plugins = Plugin::whereIn('id', $pluginIds)->get();
+
+ // Sort the collection to match plugin_ids order
+ $plugins = $plugins->sortBy(function ($plugin) use ($pluginIds) {
+ return array_search($plugin->id, $pluginIds);
+ })->values();
foreach ($plugins as $index => $plugin) {
$size = $this->getLayoutSize($index);
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index be688db..c7125c5 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -34,7 +34,7 @@ class DatabaseSeeder extends Seeder
$this->call([
ExampleRecipesSeeder::class,
- MashupPocSeeder::class,
+ // MashupPocSeeder::class,
]);
}
}
diff --git a/resources/views/flux/icon/mashup-1Tx2B.blade.php b/resources/views/flux/icon/mashup-1Tx2B.blade.php
new file mode 100644
index 0000000..e66990f
--- /dev/null
+++ b/resources/views/flux/icon/mashup-1Tx2B.blade.php
@@ -0,0 +1,40 @@
+{{-- Credit: Lucide (https://lucide.dev) --}}
+
+@props([
+ 'variant' => 'outline',
+])
+
+@php
+$classes = Flux::classes('shrink-0')
+ ->add(match($variant) {
+ 'outline' => '[:where(&)]:size-6',
+ 'solid' => '[:where(&)]:size-6',
+ 'mini' => '[:where(&)]:size-5',
+ 'micro' => '[:where(&)]:size-4',
+ });
+
+$strokeWidth = match ($variant) {
+ 'outline' => 2,
+ 'mini' => 2.25,
+ 'micro' => 2.5,
+ default => 2,
+};
+@endphp
+
+
diff --git a/resources/views/flux/icon/mashup-2Tx1B.blade.php b/resources/views/flux/icon/mashup-2Tx1B.blade.php
new file mode 100644
index 0000000..2b4d29d
--- /dev/null
+++ b/resources/views/flux/icon/mashup-2Tx1B.blade.php
@@ -0,0 +1,40 @@
+{{-- Credit: Lucide (https://lucide.dev) --}}
+
+@props([
+ 'variant' => 'outline',
+])
+
+@php
+$classes = Flux::classes('shrink-0')
+ ->add(match($variant) {
+ 'outline' => '[:where(&)]:size-6',
+ 'solid' => '[:where(&)]:size-6',
+ 'mini' => '[:where(&)]:size-5',
+ 'micro' => '[:where(&)]:size-4',
+ });
+
+$strokeWidth = match ($variant) {
+ 'outline' => 2,
+ 'mini' => 2.25,
+ 'micro' => 2.5,
+ default => 2,
+};
+@endphp
+
+
diff --git a/resources/views/livewire/devices/configure.blade.php b/resources/views/livewire/devices/configure.blade.php
index 5e0d468..011be8f 100644
--- a/resources/views/livewire/devices/configure.blade.php
+++ b/resources/views/livewire/devices/configure.blade.php
@@ -580,7 +580,19 @@ new class extends Component {
@foreach($playlist->items->sortBy('order') as $item)
- {{ $item->plugin->name }}
+ @if($item->isMashup())
+
+
+ {{ $item->getMashupName() }}
+
+
+ {{ collect($item->getMashupPluginIds())->map(fn($id) => App\Models\Plugin::find($id)->name)->join(' | ') }}
+
+
+
+ @else
+ {{ $item->plugin->name }}
+ @endif
|
user()->plugins()->where('id', '!=', $this->plugin->id)->get();
+ }
+
+ public function getRequiredPluginCount(): int
+ {
+ if ($this->mashup_layout === 'full') {
+ return 1;
+ }
+
+ return match ($this->mashup_layout) {
+ '1Lx1R', '1Tx1B' => 2, // Left-Right or Top-Bottom split
+ '1Lx2R', '2Lx1R', '2Tx1B', '1Tx2B' => 3, // Two on one side, one on other
+ '2x2' => 4, // Quadrant
+ default => 1,
+ };
+ }
+
public function addToPlaylist()
{
$this->validate([
'checked_devices' => 'required|array|min:1',
'selected_playlist' => 'required|string',
+ 'mashup_layout' => 'required|string',
+ 'mashup_plugins' => 'required_if:mashup_layout,1Lx1R,1Lx2R,2Lx1R,1Tx1B,2Tx1B,1Tx2B,2x2|array',
]);
foreach ($this->checked_devices as $deviceId) {
@@ -146,14 +169,26 @@ new class extends Component {
// Add plugin to playlist
$maxOrder = $playlist->items()->max('order') ?? 0;
- $playlist->items()->create([
- 'plugin_id' => $this->plugin->id,
- 'order' => $maxOrder + 1,
- ]);
+ if ($this->mashup_layout === 'full') {
+ $playlist->items()->create([
+ 'plugin_id' => $this->plugin->id,
+ 'order' => $maxOrder + 1,
+ ]);
+ } else {
+ // Create mashup
+ $pluginIds = array_merge([$this->plugin->id], array_map('intval', $this->mashup_plugins));
+ \App\Models\PlaylistItem::createMashup(
+ $playlist,
+ $this->mashup_layout,
+ $pluginIds,
+ $this->plugin->name . ' Mashup',
+ $maxOrder + 1
+ );
+ }
}
- $this->reset(['checked_devices', 'playlist_name', 'selected_weekdays', 'active_from', 'active_until', 'selected_playlist']);
+ $this->reset(['checked_devices', 'playlist_name', 'selected_weekdays', 'active_from', 'active_until', 'selected_playlist', 'mashup_layout', 'mashup_plugins']);
Flux::modal('add-to-playlist')->close();
}
@@ -181,7 +216,8 @@ new class extends Component {
public function renderLayoutWithTitleBar(): string
{
return <<
+@props(['size' => 'full'])
+
@@ -193,7 +229,8 @@ HTML;
public function renderLayoutBlank(): string
{
return <<
+@props(['size' => 'full'])
+
@@ -270,15 +307,16 @@ HTML;
-
+
|