Close Menu
  • Home
  • Cd-player
  • Headphones
  • Microphones
  • Mp3-players
  • Receivers and Amplifiers
  • Speaker
Search

Subscribe to Updates

Get the latest creative news from FooBar about art, design and business.

[wpforms id="14044" title="false"]
What's Hot

Disney Mixes it Up with Pint-Sized MP3 Player

21 June 2024

Onkyo C-N7050 review | What Hi-Fi?

21 June 2024

The best gaming speakers of 2024: Expert recommended

21 June 2024
Facebook X (Twitter) Instagram
Facebook X (Twitter) Instagram
Dutchieeaudio
  • Home
  • Cd-player
  • Headphones
  • Microphones
  • Mp3-players
  • Receivers and Amplifiers
  • Speaker
Dutchieeaudio
Home»Mp3-players»Learn Livewire 3, Volt, and Folio by building a podcast player
Mp3-players

Learn Livewire 3, Volt, and Folio by building a podcast player

dutchieeaudio.comBy dutchieeaudio.com10 November 2023No Comments10 Mins Read
Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
Share
Facebook Twitter LinkedIn Pinterest Email

Yesterday, the Laravel staff launched Laravel Folio – a robust page-based router designed to simplify routing in Laravel functions. Right this moment, they released Volt -an elegantly crafted purposeful API for Livewire, permitting a part’s PHP logic and Blade templates to coexist in the identical file with lowered boilerplate.

Though they could be used individually, I believe utilizing them collectively is a brand new, extremely productive technique to construct Laravel apps.

On this article, I’ll train you methods to construct a easy app that lists out episodes of the Laravel Information podcast and permits customers to play them, with a participant that may seamlessly proceed enjoying throughout web page hundreds.

Setup Livewire, Volt, and Folio

To get began, we have to create a brand new Laravel app and set up Livewire, Volt, Folio, and Sushi (to make some dummy knowledge).

laravel new

 

composer require livewire/livewire:^3.0@beta livewire/volt:^1.0@beta laravel/folio:^1.0@beta calebporzio/sushi

Livewire v3, Volt, and Folio are all nonetheless in beta. They need to be fairly secure, however use them at your individual danger.

After requiring the packages, we have to run php artisan volt:set up and php artisan folio:set up. This may scaffold out some folders and repair suppliers Volt and Folio want.

The Episode mannequin

For dummy knowledge, I will create a Sushi mannequin. Sushi is a package deal written by Caleb Pozio that permits you to create Eloquent fashions that question their knowledge from an array written instantly within the mannequin file. This works nice if you’re constructing instance apps or have knowledge that does not want to alter fairly often.

Create a mannequin, then take away the HasFactory trait and change it with the Sushi trait. I added the small print of the 4 newest Laravel Information Podcast episodes as the information for this instance.

I will not go into element on how all this works since this is not the purpose of the article, and you may doubtless use an actual Eloquent mannequin when you have been to construct your individual podcast participant.

<?php

 

namespace AppModels;

 

use IlluminateDatabaseEloquentModel;

use SushiSushi;

 

class Episode extends Mannequin

use Sushi;

 

protected $casts = [

'released_at' => 'datetime',

];

 

protected $rows = [

[

'number' => 195,

'title' => 'Queries, GPT, and sinking downloads',

'notes' => '...',

'audio' => 'https://media.transistor.fm/c28ad926/93e5fe7d.mp3',

'image' => 'https://images.transistor.fm/file/transistor/images/show/6405/full_1646972621-artwork.jpg',

'duration_in_seconds' => 2579,

'released_at' => '2023-07-06 10:00:00',

],

[

'number' => 194,

'title' => 'Squeezing lemons, punching cards, and bellowing forges',

'notes' => '...',

'audio' => 'https://media.transistor.fm/6d2d53fe/f70d9278.mp3',

'image' => 'https://images.transistor.fm/file/transistor/images/show/6405/full_1646972621-artwork.jpg',

'duration_in_seconds' => 2219,

'released_at' => '2023-06-21 10:00:00',

],

[

'number' => 193,

'title' => 'Precognition, faking Stripe, and debugging Blade',

'notes' => '...',

'audio' => 'https://media.transistor.fm/d434305e/975fbb28.mp3',

'image' => 'https://images.transistor.fm/file/transistor/images/show/6405/full_1646972621-artwork.jpg',

'duration_in_seconds' => 2146,

'released_at' => '2023-06-06 10:00:00',

],

[

'number' => 192,

'title' => 'High octane, sleepy code, and Aaron Francis',

'notes' => '...',

'audio' => 'https://media.transistor.fm/b5f81577/c58c90c8.mp3',

'image' => 'https://images.transistor.fm/file/transistor/images/show/6405/full_1646972621-artwork.jpg',

'duration_in_seconds' => 1865,

'released_at' => '2023-05-24 10:00:00',

],

// ...

];

The structure view

We’ll want a structure file to load Tailwind, add a emblem, and add some fundamental styling. Since Livewire and Alpine mechanically inject their scripts and kinds now, we do not even have to load these within the structure! We’ll create the structure as an nameless Blade part at sources/views/parts/structure.blade.php.

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta identify="viewport" content material="width=device-width, initial-scale=1.0" />

<title>Laravel Information Podcast Participant</title>

<script src="https://cdn.tailwindcss.com?plugins=typography"></script>

</head>

<physique class="min-h-screen bg-gray-50 font-sans text-black antialiased">

<div class="mx-auto max-w-2xl px-6 py-24">

<a

href="/episodes"

class="mx-auto flex max-w-max items-center gap-3 font-bold text-[#FF2D20] transition hover:opacity-80"

>

<img

src="/photos/emblem.svg"

alt="Laravel Information"

class="mx-auto w-12"

/>

<span>Laravel Information Podcast</span>

</a>

 

<div class="py-10"> $slot </div>

</div>

</physique>

</html>

The episode checklist web page

First, we’d like a web page to show all of the episodes of the podcast.

Utilizing Folio, we are able to simply create a brand new web page within the sources/views/pages listing, and Laravel will mechanically create a route for that web page. We would like our path to be /episodesso we are able to run php artisan make:folio episodes/index. That can create a clean view at sources/views/pages/episodes/index.blade.php.

On this web page, we’ll insert the structure part, then loop over all of the podcast episodes. Volt gives namespaced features for many of the Livewire options. Right here, we’ll open common <?php ?> open and shut tags. Inside these, we’ll use the computed operate to create an $episodes variable that runs a question to get all of the Episode fashions ($episodes = computed(fn () => Episode::get());). We will entry the computed property within the template utilizing $this->episodes.

I additionally created a $formatDuration variable that is a operate to format every episode’s duration_in_seconds property to a readable format. We will name that operate within the template utilizing $this->formatDuration($episode->duration_in_seconds).

We additionally have to wrap the dynamic performance on the web page within the @volt directive to register it as an “nameless Livewire part” throughout the Folio web page.

<?php

 

use AppModelsEpisode;

use IlluminateSupportStringable;

use operate LivewireVoltcomputed;

use operate LivewireVoltstate;

 

$episodes = computed(fn () => Episode::get());

 

$formatDuration = operate ($seconds) ...

return str(date('Gh im ss', $seconds))

->trim('0h ')

->explode(' ')

->mapInto(Stringable::class)

->every->ltrim('0')

->be part of(' ');

;

 

?>

 

<x-layout>

@volt

<div class="rounded-xl border border-gray-200 bg-white shadow">

<ul class="divide-y divide-gray-100">

@foreach ($this->episodes as $episode)

<li

wire:key=" $episode->quantity "

class="flex flex-col items-start gap-x-6 gap-y-3 px-6 py-4 sm:flex-row sm:items-center sm:justify-between"

>

<div>

<h2>

No. $episode->quantity - $episode->title

</h2>

<div

class="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-gray-500"

>

<p>

Launched:

$episode->released_at->format('M j, Y')

</p>

&middot;

<p>

Length:

$this->formatDuration($episode->duration_in_seconds)

</p>

</div>

</div>

<button

kind="button"

class="flex shrink-0 items-center gap-1 text-sm font-medium text-[#FF2D20] transition hover:opacity-60"

>

<img

src="/photos/play.svg"

alt="Play"

class="h-8 w-8 transition hover:opacity-60"

/>

<span>Play</span>

</button>

</li>

@endforeach

</ul>

</div>

@endvolt

</x-layout>

The episode participant

From there, we have to add some interactivity. I wish to add an episode participant so we are able to take heed to the episodes from the episode checklist. This could be a common Blade part we render within the structure file.

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<meta identify="viewport" content material="width=device-width, initial-scale=1.0" />

<title>Laravel Information Podcast Participant</title>

<script src="https://cdn.tailwindcss.com?plugins=typography"></script>

</head>

<physique class="min-h-screen bg-gray-50 font-sans text-black antialiased">

<div class="mx-auto max-w-2xl px-6 py-24">

<a

href="/episodes"

class="mx-auto flex max-w-max items-center gap-3 font-bold text-[#FF2D20] transition hover:opacity-80"

>

<img

src="/photos/emblem.svg"

alt="Laravel Information"

class="mx-auto w-12"

/>

<span>Laravel Information Podcast</span>

</a>

 

<div class="py-10"> $slot </div>

 

<x-episode-player />

</div>

</physique>

</html>

We will create that part by including a sources/views/parts/episode-player.blade.php file. Contained in the part, we’ll add an <audio> factor with some Alpine code to retailer the energetic episode and a operate that updates the energetic episode and begins the audio. We’ll solely present the participant if an energetic episode is about, and we’ll add a pleasant fade transition to the wrapper.

<div

x-data="

activeEpisode: null,

play(episode)

this.activeEpisode = episode

 

this.$nextTick(() =>

this.$refs.audio.play()

)

,

"

x-show="activeEpisode"

x-transition.opacity.period.500ms

class="fastened inset-x-0 bottom-0 w-full border-t border-gray-200 bg-white"

type="show: none"

>

<div class="mx-auto max-w-xl p-6">

<h3

x-text="`Enjoying: No. $activeEpisode?.quantity - $activeEpisode?.title`"

class="text-center text-sm font-medium text-gray-600"

></h3>

<audio

x-ref="audio"

class="mx-auto mt-3"

:src="activeEpisode?.audio"

controls

></audio>

</div>

</div>

If we reload the web page, we do not see any modifications. That is as a result of we have not added a technique to play episodes. We’ll use occasions to speak from our Livewire parts to the participant. First, within the participant, we’ll add x-on:play-episode.window="play($occasion.element)" to hear for the play-episode occasion on the window, then name the play operate.

<div

x-data="

activeEpisode: null,

play(episode)

this.activeEpisode = episode

 

this.$nextTick(() =>

this.$refs.audio.play()

)

,

"

x-on:play-episode.window="play($occasion.element)"

...

>

<!-- ... -->

</div>

Subsequent, again within the episodes/index web page, we’ll add a click on listener on the play buttons for every episode. The buttons will dispatch the play-episode occasion, which will probably be acquired by the episode participant and dealt with there.

<button

x-data

x-on:click on="$dispatch('play-episode', @js($episode))"

...

>

<img

src="/photos/play.svg"

alt="Play"

class="h-8 w-8 transition hover:opacity-60"

/>

<span>Play</span>

</button>

The episode particulars web page

Subsequent, I might like so as to add an episode particulars web page to show every episode’s present notes and different particulars.

Folio has some fairly cool conventions for route mannequin binding in your filenames. To make an equal route for /episodes/episode:idcreate a web page at sources/views/pages/episodes/[Episode].blade.php. To make use of a route parameter aside from the first key, you need to use the [Model:some_other_key].blade.php syntax in your filename. I wish to use the episode quantity within the URL, so we’ll create a file at sources/views/pages/episodes/[Episode:number].blade.php.

Folio will mechanically question the Episode fashions for an episode with the quantity we move within the URL and make that obtainable as an $episode variable in our <?php ?> code. We will then convert that to a Livewire property utilizing Volt’s state operate.

We’ll additionally embody a play button on this web page so customers can play an episode whereas viewing its particulars.

<?php

use IlluminateSupportStringable;

use operate LivewireVoltstate;

 

state(['episode' => fn () => $episode]);

 

$formatDuration = operate ($seconds) ...

return str(date('Gh im ss', $seconds))

->trim('0h ')

->explode(' ')

->mapInto(Stringable::class)

->every->ltrim('0')

->be part of(' ');

;

?>

 

<x-layout>

@volt

<div class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow">

<div class="p-6">

<div class="flex items-center justify-between gap-8">

<div>

<h2 class="text-xl font-medium">

No. $episode->quantity -

$episode->title

</h2>

<div

class="mt-1 flex items-center gap-3 text-sm text-gray-500"

>

<p>

Launched:

$episode->released_at->format('M j, Y')

</p>

&middot;

<p>

Length:

$this->formatDuration($episode->duration_in_seconds)

</p>

</div>

</div>

 

<button

x-on:click on="$dispatch('play-episode', @js($episode))"

kind="button"

class="flex items-center gap-1 text-sm font-medium text-[#FF2D20] transition hover:opacity-60"

>

<img

src="/photos/play.svg"

alt="Play"

class="h-8 w-8 transition hover:opacity-60"

/>

<span>Play</span>

</button>

</div>

<div class="prose prose-sm mt-4">

!! $episode->notes !!

</div>

</div>

<div class="bg-gray-50 px-6 py-4">

<a

href="/episodes"

class="text-sm font-medium text-gray-600"

>

&larr; Again to episodes

</a>

</div>

</div>

@endvolt

</x-layout>

Now, we have to hyperlink to the small print web page from the index web page. Again within the episodes/index web page, let’s wrap every episode’s <h2> in an anchor tag.

@foreach ($this->episodes as $episode)

<li

wire:key=" $episode->quantity "

class="flex flex-col items-start gap-x-6 gap-y-3 px-6 py-4 sm:flex-row sm:items-center sm:justify-between"

>

<div>

<a

href="/episodes/ $episode->quantity "

class="transition hover:text-[#FF2D20]"

>

<h2>

No. $episode->quantity -

$episode->title

</h2>

</a>

</div>

-- ... --

</li>

@endforeach

SPA-mode

We’re virtually there. The app seems fairly good and features properly, however there’s one challenge. If a consumer is listening to an episode, and navigates to a special web page, the episode participant loses its energetic episode state and disappears.

Fortunately, Livewire has the wire:navigate and the @persist directive to assist with these issues now!

In our structure file, let’s wrap the brand and episode participant in @persist blocks. Livewire will detect this and skip re-rendering these blocks after we change pages.

<!DOCTYPE html>

<html lang="en">

...

<physique class="min-h-screen bg-gray-50 font-sans text-black antialiased">

<div class="mx-auto max-w-2xl px-6 py-24">

@persist('emblem')

<a

href="/episodes"

class="mx-auto flex max-w-max items-center gap-3 font-bold text-[#FF2D20] transition hover:opacity-80"

>

<img

src="/photos/emblem.svg"

alt="Laravel Information"

class="mx-auto w-12"

/>

<span>Laravel Information Podcast</span>

</a>

@endpersist

 

<div class="py-10"> $slot </div>

 

@persist('participant')

<x-episode-player />

@endpersist

</div>

</physique>

</html>

Lastly, we have to add the wire:navigate attribute to all of the hyperlinks by way of the app. For instance:

<a

href="/episodes/ $episode->quantity "

class="transition hover:text-[#FF2D20]"

wire:navigate

>

<h2>

No. { $episode->quantity } -

$episode->title

</h2>

</a>

If you use the wire:navigate attribute, behind the scenes, Livewire will fetch the brand new web page’s contents utilizing AJAX, then magically swap out the contents in your browser with out doing a full web page reload. This makes web page hundreds really feel extremely quick and permits options like persist to work! It permits options that beforehand you might solely accomplish by constructing a SPA.

Conclusion

This was a very enjoyable demo app to construct whereas studying Volt and Folio. I’ve uploaded the demo app right here if you wish to see the complete supply code or attempt it out your self!

What do you suppose? Is Livewire v3 + Volt + Folio the best stack for constructing Laravel apps now? I believe it is actually cool and would possibly really feel extra acquainted to people who find themselves used to constructing apps in JavaScript frameworks like Subsequent.js and Nuxt.js. It is also good to have all of your code for a web page collocated – styling (through Tailwind), JS (through Alpine), and backend code multi function file. Ship me your ideas on Twitter!



Source link

Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
Previous ArticleAirPods Black Friday deals — 5 best sales I’d shop right now
Next Article Save 50% on Sony’s SRS-XB13 Bluetooth Speaker at $30 (2023 low)
dutchieeaudio.com
  • Website

Related Posts

Mp3-players

Disney Mixes it Up with Pint-Sized MP3 Player

21 June 2024
Mp3-players

5 best MP3 players that are making a comeback, in UAE, for 2024

21 June 2024
Mp3-players

How to use an old iPod in 2024

12 June 2024
Add A Comment

Comments are closed.

Top Posts

Disney Mixes it Up with Pint-Sized MP3 Player

21 June 2024

boAt Rockerz 370 Bluetooth Headphones price drops with a 60% discount; Check the offer now on Amazon!

12 August 2023

These are the Bose QuietComfort Ultra headphones — now with spatial audio

12 August 2023
Stay In Touch
  • Facebook
  • YouTube
  • TikTok
  • WhatsApp
  • Twitter
  • Instagram
Latest Reviews

Subscribe to Updates

Get the latest tech news from FooBar about tech, design and biz.

[wpforms id="14044" title="false"]
About Us

This website is all about providing information related to the Audio gadgets thats really usefull for you.
Thank You!

Legal Pages
  • About Us
  • Contact Us
  • Disclaimer
  • Privacy Policy
  • Newsletter
  • 1721260058.97
  • xtw183877e04
  • 1721365373.41
  • xtw18387578d
  • 1721377124.95
  • xtw18387ac27
  • 1721459042.14
  • xtw183875992
  • 1721496721.65
  • xtw18387aff1
  • 1721550036.77
  • xtw183870926
  • 1721608772.46
  • xtw183872112
  • 1721642059.15
  • xtw18387ce5c
  • 1721722731.73
  • xtw18387a01c
  • 1721732666.61
  • xtw18387344c
  • 1721826265.77
  • xtw18387b73d
  • 1721845326.54
  • xtw18387c0ab
  • 1721919029.77
  • xtw183879928
  • 1721963272.34
  • xtw18387623a
  • 1722011094.34
  • xtw18387c60d
  • 1722083025.69
  • xtw183870438
  • 1722100133.88
  • xtw183879b14
  • 1722189810.87
  • xtw183879388
  • 1722200970.52
  • xtw18387e13f
  • 1722286548.66
  • xtw18387c911
  • 1722330244.57
  • xtw18387223b
  • 1722380823.25
  • xtw183876d45
  • 1722581742.45
  • xtw183871615
  • 1722954911.47
  • xtw18387aa3e
  • 1722980755.02
  • xtw18387c097
  • 1723109026.22
  • xtw183876bb4
  • 1723163087.89
  • xtw18387cf1b
  • 1723250845.2
  • xtw18387d9ca
  • 1723273213.76
  • xtw18387aa3e
  • 1723638833.62
  • xtw18387d01e
  • 1723903409.92
  • xtw183878a37
  • 1724042563.97
  • xtw18387c379
  • 1724319326.97
  • xtw1838754c5
  • 1724493323.11
  • xtw183875386
  • 1724818263.93
  • xtw18387734e
  • 1724830961.6
  • xtw183877516
  • 1725042692.45
  • xtw183879ace
  • 1725149770.06
  • xtw18387ca3a
  • 1725252354.37
  • xtw1838712d5
  • 1725678567.46
  • xtw18387421e
  • 1726039009.75
  • xtw18387d393
  • 1726238764.3
  • xtw1838794e1
  • 1726474254.94
  • xtw183873622
  • 1726640092.34
  • xtw18387e24b
  • 1726703235.82
  • xtw18387ef6e
  • 1726757882.84
  • xtw18387cf02
  • 1726873847.52
  • xtw1838797f1
  • 1726943818.71
  • xtw183877557
  • 1726988971.29
  • xtw18387001f
  • 1727102306.75
  • xtw183876e44
  • 1727178650.24
  • xtw18387692f
  • 1727217964.9
  • xtw183870f2a
  • 1727367160.35
  • xtw18387a1fe
  • 1727489615.44
  • xtw183874087
  • 1727524046.0
  • xtw18387013f
  • 1727633578.73
  • xtw18387b30b
  • 1727718636.19
  • xtw18387e053
  • 1727747856.84
  • xtw1838788bb
  • 1727863954.25
  • xtw183878141
  • 1727989549.99
  • xtw1838755b9
  • 1728053558.78
  • xtw183870782
  • 1728369151.96
  • xtw183874350
  • 1728500424.41
  • xtw183874b10
  • 1728552589.46
  • xtw18387ca03
  • 1728625224.51
  • xtw1838702bc
  • 1728751187.75
  • xtw18387757d
  • 1728870534.65
  • xtw18387925b
  • 1728879125.98
  • xtw183873526
  • 1728981920.73
  • xtw183870d8c
  • 1728984906.63
  • xtw18387ac1b
  • 1729006888.26
  • xtw183872102
  • 1729029837.74
  • xtw18387ac41
  • 1729076179.23
  • xtw1838730b5
  • 1729077915.32
  • xtw183872704
  • 1729107985.14
  • xtw18387dae3
  • 1729125669.99
  • xtw183874523
  • 1729161538.19
  • xtw18387b8f8
  • 1729163999.53
  • xtw18387bcd8
  • 1729192096.6
  • xtw18387f074
  • 1729221034.55
  • xtw1838779e3
  • 1729241667.13
  • xtw183875c3c
  • 1729241946.73
  • xtw1838775e7
  • 1729291868.92
  • xtw1838747b1
  • 1729319372.19
  • xtw183874081
  • 1729388868.33
  • xtw18387ae6c
  • 1729441505.34
  • xtw183879e57
  • 1729446349.31
  • xtw18387f348
  • 1729491175.42
  • xtw18387907c
  • 1729521595.82
  • xtw183873b01
  • 1729541278.96
  • xtw18387434d
  • 1729592350.13
  • xtw1838720d2
  • 1729598340.74
  • xtw18387b1fc
  • 1729643099.4
  • xtw183872268
  • 1729675867.44
  • xtw183874802
  • 1729692086.57
  • xtw1838760fb
  • 1729740406.13
  • xtw1838792b0
  • 1729751629.73
  • xtw18387c17e
  • 1729789431.04
  • xtw18387a1e5
  • 1729834050.02
  • xtw1838772fa
  • 1729844321.8
  • xtw183873453
  • 1729892934.59
  • xtw1838731a2
  • 1729912644.94
  • xtw18387cca5
  • 1729945688.04
  • xtw18387f10e
  • 1729987358.72
  • xtw18387cef2
  • xtw18387cef2
  • 1730000634.67
  • xtw18387db22
  • 1730049269.25
  • xtw183877696
  • 1730061953.84
  • xtw18387bf83
  • 1730098342.24
  • xtw1838712c3
  • 1730146293.34
  • xtw18387b0d2
  • 1730163229.75
  • xtw18387404d
  • 1730212279.08
  • xtw183879e23
  • 1730222269.84
  • xtw183874ee6
  • 1730262868.53
  • xtw183879664
  • 1730301901.67
  • xtw18387cd66
  • 1730314858.21
  • xtw183871c38
  • 1730365782.16
  • xtw18387d0e0
  • xtw18387d0e0
  • 1730382039.54
  • xtw18387c8df
  • 1730417848.46
  • xtw18387fb43
  • 1730463628.21
  • xtw183870bf1
  • 1730469942.5
  • xtw183870c22
  • 1730521550.77
  • xtw18387a72b
  • 1730545432.19
  • xtw18387570d
  • 1730574001.64
  • xtw18387daa6
  • 1730623133.08
  • xtw1838705d4
  • 1730623838.1
  • xtw18387ca3b
  • 1730674137.45
  • xtw183878545
  • 1730700578.31
  • xtw18387366f
  • 1730724715.7
  • xtw183876397
  • 1730774909.7
  • xtw18387402e
  • 1730776538.18
  • xtw183870c04
  • 1730824477.34
  • xtw183870279
  • 1730852564.75
  • xtw18387257d
  • 1730874153.36
  • xtw183876092
  • 1730924011.58
  • xtw1838727a7
  • 1730929738.14
  • xtw18387a413
  • 1730977413.06
  • xtw18387b414
  • 1731016072.48
  • xtw18387d868
  • 1731036386.97
  • xtw18387d94c
  • 1731097721.31
  • xtw1838761dc
  • 1731109040.81
  • xtw1838751bb
  • 1731160300.4
  • xtw183879b51
  • 1731202855.59
  • xtw183879680
  • 1731220833.34
  • xtw183876f74
  • 1731284010.92
  • xtw1838743d6
  • 1731294931.45
  • xtw18387c980
  • 1731348629.16
  • xtw183873961

Type above and press Enter to search. Press Esc to cancel.