update: home view

This commit is contained in:
Roardom
2023-02-24 20:38:19 -06:00
parent 2b3896057f
commit 3ae38f2509
19 changed files with 1119 additions and 2250 deletions
+222 -30
View File
@@ -18,10 +18,12 @@ use App\Models\Bookmark;
use App\Models\FeaturedTorrent;
use App\Models\FreeleechToken;
use App\Models\Group;
use App\Models\Movie;
use App\Models\Poll;
use App\Models\Post;
use App\Models\Topic;
use App\Models\Torrent;
use App\Models\Tv;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
@@ -51,50 +53,240 @@ class HomeController extends Controller
// Latest Articles/News Block
$articles = cache()->remember('latest_article', $expiresAt, fn () => Article::latest()->take(1)->get());
foreach ($articles as $article) {
$article->newNews = ($user->updated_at->subDays(3)->getTimestamp() < $article->created_at->getTimestamp()) ? 1 : 0;
$article->newNews = ($user->last_login->subDays(3)->getTimestamp() < $article->created_at->getTimestamp()) ? 1 : 0;
}
// Latest Torrents Block
$personalFreeleech = cache()->get('personal_freeleech:'.$user->id);
$newest = cache()->remember('newest_torrents', $expiresAt, fn () => Torrent::with(['user', 'category', 'type', 'resolution'])
->withCount(['thanks', 'comments'])
->latest()
->take(5)
->get());
$newest = cache()->remember('newest_torrents', $expiresAt, function () {
$newest = Torrent::with(['user', 'category', 'type', 'resolution'])
->withExists([
'bookmarks' => fn ($query) => $query->where('user_id', '=', auth()->id()),
'freeleechTokens' => fn ($query) => $query->where('user_id', '=', auth()->id()),
])
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
WHEN category_id IN (SELECT `id` from `categories` where `game_meta` = 1) THEN 'game'
WHEN category_id IN (SELECT `id` from `categories` where `music_meta` = 1) THEN 'music'
WHEN category_id IN (SELECT `id` from `categories` where `no_meta` = 1) THEN 'no'
END as meta
")
->withCount(['thanks', 'comments'])
->latest()
->take(5)
->get();
$seeded = cache()->remember('seeded_torrents', $expiresAt, fn () => Torrent::with(['user', 'category', 'type', 'resolution'])
->withCount(['thanks', 'comments'])
->latest('seeders')
->take(5)
->get());
$movieIds = $newest->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $newest->where('meta', '=', 'tv')->pluck('tmdb');
$gameIds = $newest->where('meta', '=', 'game')->pluck('igdb');
$leeched = cache()->remember('leeched_torrents', $expiresAt, fn () => Torrent::with(['user', 'category', 'type', 'resolution'])
->withCount(['thanks', 'comments'])
->latest('leechers')
->take(5)
->get());
$movies = Movie::with('genres')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::with('genres')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
if ($gameIds->isNotEmpty()) {
$games = \MarcReichel\IGDBLaravel\Models\Game::with(['cover' => ['url', 'image_id']])->whereIntegerInRaw('id', $gameIds);
}
$dying = cache()->remember('dying_torrents', $expiresAt, fn () => Torrent::with(['user', 'category', 'type', 'resolution'])
->withCount(['thanks', 'comments'])
->where('seeders', '=', 1)
->where('times_completed', '>=', 1)
->latest('leechers')
->take(5)
->get());
$newest = $newest->map(function ($torrent) use ($movies, $tv) {
$torrent->meta = match ($torrent->meta) {
'movie' => $movies[$torrent->tmdb] ?? null,
'tv' => $tv[$torrent->tmdb] ?? null,
'game' => $games[$torrent->igdb] ?? null,
default => null,
};
$dead = cache()->remember('dead_torrents', $expiresAt, fn () => Torrent::with(['user', 'category', 'type', 'resolution'])
->withCount(['thanks', 'comments'])
->where('seeders', '=', 0)
->latest('leechers')
->take(5)
->get());
return $torrent;
});
return $newest;
});
$seeded = cache()->remember('seeded_torrents', $expiresAt, function () {
$seeded = Torrent::with(['user', 'category', 'type', 'resolution'])
->withExists([
'bookmarks' => fn ($query) => $query->where('user_id', '=', auth()->id()),
'freeleechTokens' => fn ($query) => $query->where('user_id', '=', auth()->id()),
])
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
WHEN category_id IN (SELECT `id` from `categories` where `game_meta` = 1) THEN 'game'
WHEN category_id IN (SELECT `id` from `categories` where `music_meta` = 1) THEN 'music'
WHEN category_id IN (SELECT `id` from `categories` where `no_meta` = 1) THEN 'no'
END as meta
")
->withCount(['thanks', 'comments'])
->latest('seeders')
->take(5)
->get();
$movieIds = $seeded->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $seeded->where('meta', '=', 'tv')->pluck('tmdb');
$gameIds = $seeded->where('meta', '=', 'game')->pluck('igdb');
$movies = Movie::with('genres')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::with('genres')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
if ($gameIds->isNotEmpty()) {
$games = \MarcReichel\IGDBLaravel\Models\Game::with(['cover' => ['url', 'image_id']])->whereIntegerInRaw('id', $gameIds);
}
$seeded = $seeded->map(function ($torrent) use ($movies, $tv) {
$torrent->meta = match ($torrent->meta) {
'movie' => $movies[$torrent->tmdb] ?? null,
'tv' => $tv[$torrent->tmdb] ?? null,
'game' => $games[$torrent->igdb] ?? null,
default => null,
};
return $torrent;
});
return $seeded;
});
$leeched = cache()->remember('leeched_torrents', $expiresAt, function () {
$leeched = Torrent::with(['user', 'category', 'type', 'resolution'])
->withExists([
'bookmarks' => fn ($query) => $query->where('user_id', '=', auth()->id()),
'freeleechTokens' => fn ($query) => $query->where('user_id', '=', auth()->id()),
])
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
WHEN category_id IN (SELECT `id` from `categories` where `game_meta` = 1) THEN 'game'
WHEN category_id IN (SELECT `id` from `categories` where `music_meta` = 1) THEN 'music'
WHEN category_id IN (SELECT `id` from `categories` where `no_meta` = 1) THEN 'no'
END as meta
")
->withCount(['thanks', 'comments'])
->latest('leechers')
->take(5)
->get();
$movieIds = $leeched->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $leeched->where('meta', '=', 'tv')->pluck('tmdb');
$gameIds = $leeched->where('meta', '=', 'game')->pluck('igdb');
$movies = Movie::with('genres')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::with('genres')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
if ($gameIds->isNotEmpty()) {
$games = \MarcReichel\IGDBLaravel\Models\Game::with(['cover' => ['url', 'image_id']])->whereIntegerInRaw('id', $gameIds);
}
$leeched = $leeched->map(function ($torrent) use ($movies, $tv) {
$torrent->meta = match ($torrent->meta) {
'movie' => $movies[$torrent->tmdb] ?? null,
'tv' => $tv[$torrent->tmdb] ?? null,
'game' => $games[$torrent->igdb] ?? null,
default => null,
};
return $torrent;
});
return $leeched;
});
$dying = cache()->remember('dying_torrents', $expiresAt, function () {
$dying = Torrent::with(['user', 'category', 'type', 'resolution'])
->withExists([
'bookmarks' => fn ($query) => $query->where('user_id', '=', auth()->id()),
'freeleechTokens' => fn ($query) => $query->where('user_id', '=', auth()->id()),
])
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
WHEN category_id IN (SELECT `id` from `categories` where `game_meta` = 1) THEN 'game'
WHEN category_id IN (SELECT `id` from `categories` where `music_meta` = 1) THEN 'music'
WHEN category_id IN (SELECT `id` from `categories` where `no_meta` = 1) THEN 'no'
END as meta
")
->withCount(['thanks', 'comments'])
->where('seeders', '=', 1)
->where('times_completed', '>=', 1)
->latest('leechers')
->take(5)
->get();
$movieIds = $dying->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $dying->where('meta', '=', 'tv')->pluck('tmdb');
$gameIds = $dying->where('meta', '=', 'game')->pluck('igdb');
$movies = Movie::with('genres')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::with('genres')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
if ($gameIds->isNotEmpty()) {
$games = \MarcReichel\IGDBLaravel\Models\Game::with(['cover' => ['url', 'image_id']])->whereIntegerInRaw('id', $gameIds);
}
$dying = $dying->map(function ($torrent) use ($movies, $tv) {
$torrent->meta = match ($torrent->meta) {
'movie' => $movies[$torrent->tmdb] ?? null,
'tv' => $tv[$torrent->tmdb] ?? null,
'game' => $games[$torrent->igdb] ?? null,
default => null,
};
return $torrent;
});
return $dying;
});
$dead = cache()->remember('dead_torrents', $expiresAt, function () {
$dead = Torrent::with(['user', 'category', 'type', 'resolution'])
->withExists([
'bookmarks' => fn ($query) => $query->where('user_id', '=', auth()->id()),
'freeleechTokens' => fn ($query) => $query->where('user_id', '=', auth()->id()),
])
->selectRaw("
CASE
WHEN category_id IN (SELECT `id` from `categories` where `movie_meta` = 1) THEN 'movie'
WHEN category_id IN (SELECT `id` from `categories` where `tv_meta` = 1) THEN 'tv'
WHEN category_id IN (SELECT `id` from `categories` where `game_meta` = 1) THEN 'game'
WHEN category_id IN (SELECT `id` from `categories` where `music_meta` = 1) THEN 'music'
WHEN category_id IN (SELECT `id` from `categories` where `no_meta` = 1) THEN 'no'
END as meta
")
->withCount(['thanks', 'comments'])
->where('seeders', '=', 0)
->latest('leechers')
->take(5)
->get();
$movieIds = $dead->where('meta', '=', 'movie')->pluck('tmdb');
$tvIds = $dead->where('meta', '=', 'tv')->pluck('tmdb');
$gameIds = $dead->where('meta', '=', 'game')->pluck('igdb');
$movies = Movie::with('genres')->whereIntegerInRaw('id', $movieIds)->get()->keyBy('id');
$tv = Tv::with('genres')->whereIntegerInRaw('id', $tvIds)->get()->keyBy('id');
if ($gameIds->isNotEmpty()) {
$games = \MarcReichel\IGDBLaravel\Models\Game::with(['cover' => ['url', 'image_id']])->whereIntegerInRaw('id', $gameIds);
}
$dead = $dead->map(function ($torrent) use ($movies, $tv) {
$torrent->meta = match ($torrent->meta) {
'movie' => $movies[$torrent->tmdb] ?? null,
'tv' => $tv[$torrent->tmdb] ?? null,
'game' => $games[$torrent->igdb] ?? null,
default => null,
};
return $torrent;
});
return $dead;
});
// Latest Topics Block
$topics = cache()->remember('latest_topics', $expiresAt, fn () => Topic::with('forum')->latest()->take(5)->get());
// Latest Posts Block
$posts = cache()->remember('latest_posts', $expiresAt, fn () => Post::with('topic', 'user')->latest()->take(5)->get());
$posts = cache()->remember('latest_posts', $expiresAt, fn () => Post::with('topic', 'user')->withCount('authorPosts', 'authorTopics')->latest()->take(5)->get());
// Online Block
$users = cache()->remember('online_users', $expiresAt, fn () => User::with('group', 'privacy')
+42 -109
View File
@@ -1,120 +1,53 @@
<template>
<div class="message-input">
<div class="wrap" id="frameWrap">
<div class="width-table" style="margin: auto; padding-bottom: 5px; height: 22px">
<div class="width-75" style="padding: 0; height: 22px">
<div
style="padding-left: 0; margin-left: 0; padding-bottom: 0; margin-bottom: 0"
v-if="$parent.bot > 0 && $parent.activeTab.substr(0, 3) == 'bot'"
>
<span class="badge-extra" style="margin-left: 0; padding-left: 5px; margin-bottom: 0"
>{{ $parent.botName }} can accept messages from any tab if you type:
<strong>/{{ $parent.botCommand }} help</strong></span
>
</div>
<div
class="typing pull-left"
v-if="
$parent.target < 1 &&
$parent.bot < 1 &&
$parent.activePeer &&
$parent.activePeer.username != ''
"
style="padding-left: 0; margin-left: 0; padding-bottom: 0; margin-bottom: 0"
>
<span class="badge-extra" style="margin-left: 0; padding-left: 5px; margin-bottom: 0">{{
$parent.activePeer ? $parent.activePeer.username + ' is typing ...' : '*'
}}</span>
</div>
<div v-if="$parent.tab != 'userlist'" style="margin-right: 5px; display: inline-block">
<span>Audio: </span>
<i
v-if="
$parent.room &&
$parent.room > 0 &&
$parent.bot < 1 &&
$parent.target < 1 &&
$parent.tab != 'userlist'
"
@click.prevent="$parent.changeAudible('room', $parent.room, $parent.listening ? 0 : 1)"
:class="$parent.listening ? 'fa fa-bell pointee' : 'fa fa-bell-slash pointee'"
:style="`color: ${$parent.listening ? 'rgb(0,102,0)' : 'rgb(204,0,0)'}`"
></i>
<i
v-if="$parent.bot && $parent.bot >= 1 && $parent.target < 1 && $parent.tab != 'userlist'"
@click.prevent="$parent.changeAudible('bot', $parent.bot, $parent.listening ? 0 : 1)"
:class="$parent.listening ? 'fa fa-bell pointee' : 'fa fa-bell-slash pointee'"
:style="`color: ${$parent.listening ? 'rgb(0,102,0)' : 'rgb(204,0,0)'}`"
></i>
<i
v-if="$parent.target && $parent.target >= 1 && $parent.bot < 1 && $parent.tab != 'userlist'"
@click.prevent="$parent.changeAudible('target', $parent.target, $parent.listening ? 0 : 1)"
:class="$parent.listening ? 'fa fa-bell pointee' : 'fa fa-bell-slash pointee'"
:style="`color: ${$parent.listening ? 'rgb(0,102,0)' : 'rgb(204,0,0)'}`"
></i>
</div>
<div style="margin-right: 5px; display: inline-block">
<span style="margin-right: 5px">Status: </span>
<i
v-for="status in $parent.statuses"
@click="$emit('changedStatus', status.id)"
:class="status.icon ? status.icon + ' pointee mr-5' : 'fa fa-dot-circle-o pointee mr-5'"
:style="`color: ${status.color}`"
></i>
<span>
<chatrooms-dropdown
:current="user.chatroom.id"
:chatrooms="$parent.chatrooms"
class="pull-right"
@changedRoom="$parent.changeRoom"
>
</chatrooms-dropdown>
</span>
</div>
</div>
</div>
<div class="chatbox__message-input">
<div
class="chatbox__bot-info"
v-if="$parent.bot > 0 && $parent.activeTab.substr(0, 3) == 'bot'"
>
<span>
{{ $parent.botName }} can accept messages from any tab if you type:
<strong>/{{ $parent.botCommand }} help</strong>
</span>
</div>
<div class="row" style="margin: auto">
<div class="col-md-12">
<textarea
id="chat-message"
name="message"
placeholder="Write your message..."
cols="30"
rows="5"
send="true"
style="width: 100%"
></textarea>
</div>
<div
class="chatbox__typing"
v-if="
$parent.target < 1 &&
$parent.bot < 1 &&
$parent.activePeer &&
$parent.activePeer.username != ''
"
>
<span>{{
$parent.activePeer ? $parent.activePeer.username + ' is typing ...' : '*'
}}</span>
</div>
<div class="chatbox__textarea-container form__group">
<textarea
class="chatbox__textarea form__textarea"
name="message"
placeholder=""
send="true"
></textarea>
<label class="form__label form__label--floating">Write your message...</label>
</div>
</div>
</template>
<style lang="scss" scoped>
.col-md-4,
.col-md-6,
.col-md-12 {
padding: 0;
<style lang="scss">
.chatbox__message-input {
background: inherit;
}
.pointee {
cursor: pointer;
.chatbox__typing {
font-size: 12px;
padding:0 5px 5px 5px;
}
.mr-5 {
margin-right: 5px;
.chatbox__bot-info {
font-size: 12px;
padding: 6px;
}
.info {
.badge-extra {
width: auto;
margin: 0 8px 0 0;
}
i {
&.fa {
&:hover {
cursor: pointer;
}
}
}
.chatbox__textarea-container {
margin: 0 6px 6px 6px;
width: calc(100% - 2 * 6px);
}
</style>
<script>
+148 -71
View File
@@ -1,84 +1,161 @@
<template>
<div class="messages">
<ul class="list-group">
<li class="sent" v-for="message in messages">
<a target="_blank" :href="`/users/${message.user.username}`">
<img
v-if="message.user.id !== 1"
class="chat-user-image"
:style="`border: 3px solid ${message.user.chat_status.color};`"
:src="message.user.image ? `/files/img/${message.user.image}` : '/img/profile.png'"
alt=""
/>
</a>
<h4 class="list-group-item-heading bot">
<span class="badge-user text-bold" :style="userStyles(message.user)">
<i
v-if="(message.user && message.user.id > 1) || (message.bot && message.bot.id >= 1)"
:class="message.user.group.icon"
>
</i>
<i
v-if="message.user && message.user.id <= 1 && (!message.bot || message.bot.id < 1)"
class="fas fa-bell"
>
</i>
<a
v-if="message.user && message.user.id > 1"
@click="pmUser(message.user)"
:style="groupColor(message.user)"
>
{{ message.user.username }}
</a>
<a
v-if="message.bot && message.bot.id >= 1 && (!message.user || message.user.id < 2)"
:style="groupColor(message.user)"
>
{{ message.bot.name }}
</a>
<i
v-if="message.user.id != 1 && canMod(message)"
@click="deleteMessage(message.id)"
class="fa fa-times text-red"
>
</i>
</span>
<ul class="chatbox__messages">
<li :class="message.user.id === 1 ? 'chatbox-message chatbox-message--bot' : 'chatbox-message'" v-for="message in messages">
<a target="_blank" :href="`/users/${message.user.username}`" class="chatbox-message__link">
<img
v-if="message.user.id !== 1"
class="chatbox-message__avatar"
:style="`border: 3px solid ${message.user.chat_status.color};`"
:src="message.user.image ? `/files/img/${message.user.image}` : '/img/profile.png'"
alt=""
/>
</a>
<address class="chatbox-message__header">
<span class="chatbox-message__author" :style="userStyles(message.user)">
<i
v-if="(message.user && message.user.id > 1) || (message.bot && message.bot.id >= 1)"
:class="message.user.group.icon"
>
</i>
<i
v-if="message.user && message.user.id <= 1 && (!message.bot || message.bot.id < 1)"
class="fas fa-bell"
>
</i>
<a
v-if="message.user && message.user.id > 1"
@click="pmUser(message.user)"
:style="groupColor(message.user)"
>
{{ message.user.username }}
</a>
<a
v-if="message.bot && message.bot.id >= 1 && (!message.user || message.user.id < 2)"
:style="groupColor(message.user)"
>
{{ message.bot.name }}
</a>
</span>
<menu class="chatbox-message__actions">
<button
v-if="message.user.id != 1 && canMod(message)"
@click="deleteMessage(message.id)"
class="form__standard-icon-button form__standard-icon-button--short form__standard-icon-button--skinny"
>
<i class="fa fa-times text-red"></i>
</button>
<button
v-if="message.user && message.user.id > 1 && message.user.id != $parent.auth.id"
@click.prevent="$parent.forceMessage(message.user.username)"
class="form__standard-icon-button form__standard-icon-button--short form__standard-icon-button--skinny"
>
<i class="fas fa-envelope pointee"></i>
</a>
<a
<i class="fas fa-envelope"></i>
</button>
<button
v-if="message.user && message.user.id > 1 && message.user.id != $parent.auth.id"
@click.prevent="$parent.forceGift(message.user.username)"
class="form__standard-icon-button form__standard-icon-button--short form__standard-icon-button--skinny"
>
<i class="fas fa-gift pointee"></i>
</a>
<span v-if="message.user.id !== 1" class="text-muted">
{{ message.created_at | diffForHumans }}
</span>
</h4>
<div
@click="checkBot($event, message)"
:class="message.user.id === 1 ? 'system text-bright bot' : 'text-bright'"
v-html="message.message"
></div>
</li>
</ul>
</div>
<i class="fas fa-gift"></i>
</button>
</menu>
<span v-if="message.user.id !== 1" class="chatbox-message__timestamp">
{{ message.created_at | diffForHumans }}
</span>
</address>
<div
@click="checkBot($event, message)"
class="chatbox-message__content bbcode-rendered"
v-html="message.message"
></div>
</li>
</ul>
</template>
<style lang="scss" scoped>
.pointee {
cursor: pointer;
<style lang="scss">
.chatbox__messages {
padding: 10px 0;
list-style-type: none;
background-color: inherit !important; /* Overrides theming */
display: flex;
flex-direction: column-reverse;
align-items: flex-start;
row-gap: 10px;
overflow-y: auto;
}
.bot {
display: inline-block;
vertical-align: top;
.chatbox-message {
display: grid;
grid-template-columns: 0 auto auto 1fr auto;
grid-template-rows: min-content auto;
grid-template-areas:
'avatar author actions timestamp'
'avatar content content content';
gap: 0 4px;
align-items: center;
padding: 12px 16px;
margin-left: 58px;
border-radius: 20px;
font-size: 13px;
color: var(--message-bubble-fg, currentColor);
background-color: var(--message-bubble-bg, inherit);
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12), 0 1px 3px 0 rgba(0, 0, 0, 0.2);
width: fit-content;
max-width: 100%
}
.chatbox-message__header {
display: contents;
}
.chatbox-message__link {
display: contents;
}
.chatbox-message__avatar {
grid-area: avatar;
position: relative;
left: -58px;
bottom: -12px;
border-radius: 50%;
width: 36px;
align-self: self-end;
background-color: transparent;
}
.chatbox-message__author {
grid-area: author;
margin: 0;
font-size: 13px;
font-weight: 600;
}
.chatbox-message__timestamp {
grid-area: timestamp;
font-size: 11px;
margin: 0 8px;
white-space: nowrap;
}
.chatbox-message__actions {
grid-area: actions;
display: flex;
justify-content: flex-end;
gap: 4px;
padding: 0;
margin: 0;
}
.chatbox-message__content {
grid-area: content;
position: relative;
margin-top: 0 !important; /* can be removed once site-wide `p` styling is removed */
overflow-x: auto;
img:not(.joypixels) {
min-height: 150px;
max-height: 300px;
max-width: 500px;
}
}
</style>
<script>
+21 -36
View File
@@ -1,40 +1,25 @@
<template>
<div class="messages">
<ul class="list-group">
<li class="sent" v-for="user in users">
<div class="button-holder">
<div class="button-center">
<div class="text-left">
<a v-if="user.id !== 1" target="_blank" :href="`/users/${user.username}`">
<img
class="chat-user-image"
:style="
user &&
user.hasOwnProperty('chat_status') &&
user.chat_status.hasOwnProperty('color')
? `border: 3px solid ${user.chat_status.color};`
: ``
"
:src="user.image ? `/files/img/${user.image}` : '/img/profile.png'"
alt=""
/>
</a>
<h4 class="list-group-item-heading">
<span class="badge-user text-bold" :style="userStyles(user)">
<i :class="user.group.icon"> </i>
<a :style="groupColor(user)" @click="pmUser(user)">
{{ user.username }}
</a>
</span>
</h4>
<div :class="user.id === 1 ? 'system text-bright' : 'text-bright'"></div>
</div>
</div>
</div>
</li>
</ul>
</div>
<ul class="chatbox__messages">
<li class="chatbox-message" v-for="user in users">
<a target="_blank" :href="`/users/${user.username}`" class="chatbox-message__link">
<img
v-if="user.id !== 1"
class="chatbox-message__avatar"
:style="`border: 3px solid ${user.chat_status.color};`"
:src="user.image ? `/files/img/${user.image}` : '/img/profile.png'"
alt=""
/>
</a>
<address class="chatbox-message__header">
<span class="chatbox-message__author" :style="userStyles(user)">
<i :class="message.user.group.icon"></i>
<a :style="groupColor(user)">
{{ user.username }}
</a>
</span>
</address>
</li>
</ul>
</template>
<script>
import pmMethods from './mixins/pmMethods';
+208 -232
View File
@@ -1,183 +1,187 @@
<template>
<div
:class="
this.fullscreen == 1
? `col-md-10 col-sm-10 col-md-offset-1 chatbox panel-fullscreen`
: `col-md-10 col-sm-10 col-md-offset-1 chatbox`
"
id="chatbody"
<section
class="panelV2 chatbox"
:class="this.fullscreen == 1 ? 'panel--fullscreen' : this.widescreen == 1 ? 'panel--widescreen' : null"
audio="false"
>
<div
:class="this.fullscreen == 1 ? `clearfix visible-sm-block panel-fullscreen` : `clearfix visible-sm-block`"
></div>
<div :class="this.fullscreen == 1 ? `panel panel-chat panel-fullscreen` : `panel panel-chat`">
<div class="panel-heading" id="frameHeader">
<div class="button-holder no-space">
<div class="button-left">
<h4><i class="fas fa-comment-dots"></i> Chatbox v3.0</h4>
<header class="panel__header">
<h2 class="panel__heading">
<i class="fas fa-comment-dots"></i> Chatbox v3.0
</h2>
<div class="panel__actions">
<div class="panel__action">
<div class="form__group" v-if="room && room > 0 && bot < 1 && target < 1 && tab != 'userlist'">
<label class="form__label" @click.prevent="changeAudible('room', room, listening ? 0 : 1)">
<input type="checkbox" class="form__checkbox" :checked="listening == true">
Audio
</label>
</div>
<div class="button-right">
<a href="" view="bot" @click.prevent="startBot()" class="btn btn-xs btn-warning">
<i class="fa fa-robot"></i> {{ helpName }}
</a>
<a
href=""
view="list"
v-if="target < 1 && bot < 1 && tab != 'userlist'"
@click.prevent="changeTab('list', 'userlist')"
class="btn btn-xs btn-primary"
>
<i class="fa fa-users"></i> Users In {{ tab }}: {{ users.length }}
</a>
<a
href="#"
id="panel-fullscreen"
role="button"
:class="`btn btn-xs btn-success`"
title="Toggle Fullscreen"
@click.prevent="changeFullscreen()"
><i
:class="
this.fullscreen == 1
? `glyphicon glyphicon-resize-small`
: `glyphicon glyphicon-resize-full`
"
></i>
</a>
<div class="form__group" v-if="bot && bot >= 1 && target < 1 && tab != 'userlist'">
<label class="form__label" @click.prevent="changeAudible('bot', bot, listening ? 0 : 1)">
<input type="checkbox" class="form__checkbox" :checked="listening == true">
Audio
</label>
</div>
<div class="form__group" v-if="target && target >= 1 && bot < 1 && tab != 'userlist'">
<label class="form__label" @click.prevent="changeAudible('target', target, listening ? 0 : 1)">
<input type="checkbox" class="form__checkbox" :checked="listening == true">
Audio
</label>
</div>
</div>
</div>
<div class="panel-body" id="frameBody">
<div id="frame" @mouseover="freezeChat()" @mouseout="unfreezeChat()">
<div class="content no-space">
<div class="button-holder nav nav-tabs mb-5" id="frameTabs">
<div>
<ul role="tablist" class="nav nav-tabs no-border mb-0" v-if="boot == 1">
<li
v-for="echo in echoes"
v-if="echo.room && echo.room.name.length > 0"
:class="tab != '' && tab === echo.room.name ? 'active' : null"
>
<a
href=""
role="tab"
view="room"
@click.prevent="changeTab('room', echo.room.id)"
>
<i
:class="
checkPings('room', echo.room.id)
? 'fa fa-comment fa-beat text-success'
: 'fa fa-comment text-danger'
"
></i>
{{ echo.room.name }}
</a>
</li>
<li
v-for="echo in echoes"
v-if="echo.target && echo.target.id >= 3 && echo.target.username.length > 0"
:class="target >= 3 && target === echo.target.id ? 'active' : null"
>
<a
href=""
role="tab"
view="target"
@click.prevent="changeTab('target', echo.target.id)"
>
<i
:class="
checkPings('target', echo.target.id)
? 'fa fa-comment fa-beat text-success'
: 'fa fa-comment text-danger'
"
></i>
@{{ echo.target.username }}
</a>
</li>
<li
v-for="echo in echoes"
v-if="echo.bot && echo.bot.id >= 1 && echo.bot.name.length > 0"
:class="bot > 0 && bot === echo.bot.id ? 'active' : null"
>
<a href="" role="tab" view="bot" @click.prevent="changeTab('bot', echo.bot.id)">
<i
:class="
checkPings('bot', echo.bot.id)
? 'fa fa-comment fa-beat text-success'
: 'fa fa-comment text-danger'
"
></i>
@{{ echo.bot.name }}
</a>
</li>
</ul>
</div>
<div class="button-right-small">
<div class="nav nav-tabs no-border mb-0 mt-5">
<div class="mr-10">
<a
href=""
v-if="bot > 0"
view="exit"
@click.prevent="leaveBot(bot)"
class="btn btn-sm btn-danger"
>
<i class="fa fa-times"></i>
</a>
<a
href=""
v-if="bot < 1 && target > 0"
view="exit"
@click.prevent="leaveTarget(target)"
class="btn btn-sm btn-danger"
>
<i class="fa fa-times"></i>
</a>
<a
href=""
v-if="bot < 1 && target < 1 && tab != '' && tab != 'userlist' && room != 1"
view="exit"
@click.prevent="leaveRoom(room)"
class="btn btn-sm btn-danger"
>
<i class="fa fa-times"></i>
</a>
</div>
</div>
</div>
</div>
<chat-messages
v-if="!state.connecting && tab != '' && tab != 'userlist'"
@pm-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
:messages="msgs"
>
</chat-messages>
<chat-user-list
v-if="!state.connecting && tab === 'userlist'"
@pm-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
:users="users"
>
</chat-user-list>
</div>
<div class="panel__action">
<chatstatuses-dropdown
:current="status.id"
:chatstatuses="statuses"
@changedStatus="changeStatus"
>
</chatstatuses-dropdown>
</div>
<div class="panel__action">
<chatrooms-dropdown
:current="user.chatroom.id"
:chatrooms="chatrooms"
@changedRoom="changeRoom"
>
</chatrooms-dropdown>
</div>
<div class="panel__action">
<a
href=""
view="bot"
@click.prevent="startBot()"
class="form__button form__button--text"
>
<i class="fa fa-robot"></i> {{ helpName }}
</a>
</div>
<div class="panel__action">
<a
href=""
view="list"
v-if="target < 1 && bot < 1 && tab != 'userlist'"
@click.prevent="changeTab('list', 'userlist')"
class="form__button form__button--text"
>
<i class="fa fa-users"></i> Users In {{ tab }}: {{ users.length }}
</a>
</div>
<div class="panel__action">
<a
href="#"
id="panel-fullscreen"
role="button"
class="form__button form__button--text"
title="Toggle Widescreen"
@click.prevent="changeWidescreen()"
>
<i :class="this.widescreen == 1 ? `fas fa-compress-wide` : `fas fa-expand-wide`"></i>
</a>
</div>
<div class="panel__action">
<a
href="#"
id="panel-fullscreen"
role="button"
class="form__button form__button--text"
title="Toggle Fullscreen"
@click.prevent="changeFullscreen()"
>
<i :class="this.fullscreen == 1 ? 'fas fa-compress' : 'fas fa-expand'"></i>
</a>
</div>
</div>
<div class="panel-footer" id="frameFooter">
<chat-form
@changedStatus="changeStatus"
@message-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
@typing="isTyping"
</header>
<menu role="tablist" class="panel__tabs" v-if="boot == 1">
<li
v-for="echo in echoes"
v-if="echo.room && echo.room.name.length > 0"
:class="tab != '' && tab === echo.room.name ? 'panel__tab panel__tab--active' : 'panel__tab'"
@click.prevent="changeTab('room', echo.room.id)"
role="tab"
view="room"
>
<i :class="checkPings('room', echo.room.id) ? 'fa fa-comment fa-beat text-success' : 'fa fa-comment text-danger'"></i>
{{ echo.room.name }}
<a
href=""
v-if="bot < 1 && target < 1 && tab != '' && tab === echo.room.name && room != 1"
view="exit"
@click.prevent="leaveRoom(room)"
class="form__standard-icon-button form__standard-icon-button--short"
>
</chat-form>
</div>
<i class="fa fa-times"></i>
</a>
</li>
<li
v-for="echo in echoes"
v-if="echo.target && echo.target.id >= 3 && echo.target.username.length > 0"
:class="target >= 3 && target === echo.target.id ? 'panel__tab panel__tab--active' : 'panel__tab'"
@click.prevent="changeTab('target', echo.target.id)"
role="tab"
view="target"
>
<i :class="checkPings('target', echo.target.id) ? 'fa fa-comment fa-beat text-success' : 'fa fa-comment text-danger'"></i>
@{{ echo.target.username }}
<a
href=""
v-if="bot < 1 && target > 0 && target === echo.target.id"
view="exit"
@click.prevent="leaveTarget(target)"
class="form__standard-icon-button form__standard-icon-button--short"
>
<i class="fa fa-times"></i>
</a>
</li>
<li
v-for="echo in echoes"
v-if="echo.bot && echo.bot.id >= 1 && echo.bot.name.length > 0"
:class="bot > 0 && bot === echo.bot.id ? 'panel__tab panel__tab--active' : 'panel__tab'"
role="tab"
view="bot"
@click.prevent="changeTab('bot', echo.bot.id)"
>
<i :class="checkPings('bot', echo.bot.id) ? 'fa fa-comment fa-beat text-success' : 'fa fa-comment text-danger'"></i>
@{{ echo.bot.name }}
<a
href=""
v-if="bot > 0 && bot === echo.bot.id"
view="exit"
class="form__standard-icon-button form__standard-icon-button--short"
@click.prevent="leaveBot(bot)"
>
<i class="fa fa-times"></i>
</a>
</li>
</menu>
<div
class="chatbox__body"
@mouseover="freezeChat()"
@mouseout="unfreezeChat()"
>
<chat-messages
v-if="!state.connecting && tab != '' && tab != 'userlist'"
@pm-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
:messages="msgs"
>
</chat-messages>
<chat-user-list
v-if="!state.connecting && tab === 'userlist'"
@pm-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
:users="users"
>
</chat-user-list>
<chat-form
@changedStatus="changeStatus"
@message-sent="(o) => createMessage(o.message, o.save, o.user_id, o.receiver_id, o.bot_id)"
@typing="isTyping"
>
</chat-form>
</div>
</div>
</section>
</template>
<style lang="scss" scoped>
.panel-fullscreen {
<style lang="scss">
.panel--fullscreen {
z-index: 9999;
position: fixed;
width: 100%;
@@ -187,23 +191,27 @@
bottom: 0;
left: 0;
right: 0;
overscroll-behavior: contain;
}
.panel-footer {
padding: 5px;
margin: 0;
}
.mr-10 {
margin-right: 10px;
}
.no-border {
border-bottom: none;
border-top: none;
}
.chatbox {
.nav-tabs {
overflow-y: hidden;
}
.panel--widescreen {
margin: 0 calc(50% - 50vw + 12px)
}
.chatbox__body {
height: 98vh;
min-height: 300px;
max-height: 590px;
display: grid;
grid-template-rows: 1fr auto;
background: inherit;
.panel--fullscreen & {
max-height: unset;
}
}
.chatbox {
.typing {
height: 20px;
@@ -211,28 +219,11 @@
margin: 0;
}
}
.statuses {
i {
&:hover {
cursor: pointer;
}
}
}
.panel-body {
padding: 0;
}
.decoda-image {
min-height: 150px;
max-height: 300px;
max-width: 500px;
}
}
</style>
<script>
import ChatroomsDropdown from './ChatroomsDropdown';
import ChatstatusesDropdown from './ChatstatusesDropdown';
import ChatMessages from './ChatMessages';
import ChatForm from './ChatForm';
import ChatPms from './ChatPms';
@@ -247,6 +238,7 @@ export default {
},
components: {
ChatroomsDropdown,
ChatstatusesDropdown,
ChatMessages,
ChatForm,
ChatUserList,
@@ -272,6 +264,7 @@ export default {
audioLoaded: 0,
room: 0,
fullscreen: 0,
widescreen: 0,
startup: 0,
check: 0,
target: 0,
@@ -544,23 +537,21 @@ export default {
},
fetchBotMessages(id) {
axios.get(`/api/chat/bot/${id}`).then((response) => {
this.messages = _.reverse(response.data.data);
this.scrollToBottom();
this.messages = response.data.data;
this.state.connecting = false;
});
},
fetchPrivateMessages() {
axios.get(`/api/chat/private/messages/${this.target}`).then((response) => {
this.messages = _.reverse(response.data.data);
this.messages = response.data.data;
this.state.connecting = false;
this.scrollToBottom(true);
});
},
fetchMessages() {
axios.get(`/api/chat/messages/${this.room}`).then((response) => {
this.messages = _.reverse(response.data.data);
this.messages = response.data.data;
this.state.connecting = false;
this.scrollToBottom(true);
});
},
fetchStatuses() {
@@ -569,18 +560,16 @@ export default {
});
},
forceMessage(name) {
$('#chat-message').bbcode('/msg ' + name + ' ');
$('#chat-message').htmlcode('/msg ' + name + ' ');
$('.chatbox__textarea').text('/msg ' + name + ' ');
},
forceGift(name) {
$('#chat-message').bbcode('/gift ' + name + ' ');
$('#chat-message').htmlcode('/gift ' + name + ' ');
$('.chatbox__textarea').text('/gift ' + name + ' ');
},
freezeChat() {
this.frozen = true;
},
unfreezeChat() {
let container = $('.messages .list-group');
let container = $('.chatbox__messages');
let xy = parseInt(container.prop('offsetHeight') + container.scrollTop());
if (xy != undefined && this.frozen == true) {
if (
@@ -680,28 +669,15 @@ export default {
changeFullscreen() {
if (this.fullscreen == 1) {
this.fullscreen = 0;
$('#frameBody').css({ height: '92vh', 'min-height': '300px', 'max-height': '590px' });
$('#frameList').css({ height: 'initial', 'min-height': '300px', 'max-height': '535px' });
$('#frameHeader').css({ height: 'initial', 'min-height': 'initial', 'max-height': 'initial' });
$('#frameFooter').css({
'padding-top': '10px',
height: 'initial',
'min-height': 'initial',
'max-height': 'initial',
});
$('#frameWrap').css({ width: '100%', 'padding-top': '0px' });
} else {
this.fullscreen = 1;
$('#frameBody').css({ height: '70vh', 'min-height': '0px', 'max-height': '70vh' });
$('#frameList').css({ height: $('#frameBody').height() - $('#frameTabs').height() - 20 + 'px' });
$('#frameHeader').css({ height: '6vh', 'min-height': '0px', 'max-height': '6vh' });
$('#frameFooter').css({
'padding-top': '0px',
height: '24vh',
'min-height': '0px',
'max-height': '24vh',
});
$('#frameWrap').css({ width: '100%', 'padding-top': '5px' });
}
},
changeWidescreen() {
if (this.widescreen == 1) {
this.widescreen = 0;
} else {
this.widescreen = 1;
}
},
changeStatus(status_id) {
@@ -1,8 +1,10 @@
<template>
<select id="currentChatroom" v-model="selected" @change="changedRoom">
<option value="0" selected disabled>Join a room</option>
<option v-for="chatroom in chatrooms" :value="chatroom.id">{{ chatroom.name }}</option>
</select>
<div class="form__group">
<select id="currentChatroom" class="form__select" v-model="selected" @change="changedRoom">
<option v-for="chatroom in chatrooms" :value="chatroom.id" :selected="chatroom.id == selected">{{ chatroom.name }}</option>
</select>
<label for="currentChatroom" class="form__label form__label--floating">Join a room</label>
</div>
</template>
<script>
@@ -19,11 +21,10 @@ export default {
methods: {
changedRoom(event) {
this.$emit('changedRoom', this.selected);
this.selected = 0;
},
},
created() {
this.selected = 0;
this.selected = this.current;
},
};
</script>
@@ -0,0 +1,36 @@
<template>
<div class="form__group">
<select id="currentChatstatus" class="form__select" v-model="selected" @change="changedStatus">
<option v-for="chatstatus in chatstatuses" :value="chatstatus.id" :selected="chatstatus.id == selected">
<i
:class="chatstatus.icon ? chatstatus.icon + ' pointee mr-5' : 'fa fa-dot-circle-o pointee mr-5'"
:style="`color: ${chatstatus.color}`"
></i>
{{ chatstatus.name }}
</option>
</select>
<label for="currentChatroom" class="form__label form__label--floating">Change Chat Status</label>
</div>
</template>
<script>
export default {
props: {
current: { type: Number, default: 1 },
chatstatuses: { required: true },
},
data() {
return {
selected: 1,
};
},
methods: {
changedStatus(event) {
this.$emit('changedStatus', this.selected);
},
},
created() {
this.selected = this.current;
},
};
</script>
+57 -10
View File
@@ -39,16 +39,6 @@
text-align: center;
}
.panel__header-link {
color: var(--panel-head-fg);
&:hover {
color: var(--panel-head-fg);
filter: brightness(1.1);
text-decoration: underline;
}
}
.panel__actions {
display: flex;
flex-direction: row;
@@ -67,6 +57,63 @@
background-color: var(--panel-head-bg);
}
@media only screen and (max-width: 1100px) {
.panel__header {
position: relative;
}
.panel__action {
display: none;
}
.panel__actions {
position: absolute;
right: 0;
top: 0;
max-width: 90vw;
&::before {
content: "\22EE";
cursor: pointer;
}
&:hover, &:focus {
flex-direction: column;
align-items: stretch;
&::before {
display: none;
}
.panel__action {
display: block;
}
}
}
}
.panel__tabs {
display: flex;
overflow-x: scroll;
padding: 0;
margin: 0;
background-color: var(--data-table-th-bg);
}
.panel__tab {
background-color: var(--data-table-th-fg);
padding: 8px 16px 6px 16px;
list-style-type: none;
border-bottom: 2px solid var(--data-table-th-fg);
cursor: pointer;
white-space: nowrap;
}
.panel__tab--active {
color: #b0b0b0;
border-bottom: 2px solid #888;
}
.panel__body {
padding: 20px;
font-size: 15px;
@@ -87,6 +87,18 @@
}
}
.form__standard-icon-button--short {
padding-top: 2px;
padding-bottom: 2px;
min-height: unset;
}
.form__standard-icon-button--skinny {
padding-left: 2px;
padding-right: 2px;
min-width: unset;
}
/* Contained Icon Buttons
---------------------------------------------------------------------------- */
+13 -13
View File
@@ -1,15 +1,15 @@
.page__home {
margin: 0 calc(-1 * max(0px, 10vw - 60px)); /* Inverses the magic numbers used in the main layout styles */
}
// .page__home {
// margin: 0 calc(-1 * max(0px, 10vw - 60px)); /* Inverses the magic numbers used in the main layout styles */
// }
@media only screen and (min-width: 1600px) {
.page__home {
margin: 0 calc(-1 * max(0px, 25vw - 300px)); /* Inverses the magic numbers used in the main layout styles */
}
}
// @media only screen and (min-width: 1600px) {
// .page__home {
// margin: 0 calc(-1 * max(0px, 25vw - 300px)); /* Inverses the magic numbers used in the main layout styles */
// }
// }
@media only screen and (min-width: 2500px) {
.page__home {
margin: 0 calc(-1 * max(0px, 45vw - 800px)); /* Inverses the magic numbers used in the main layout styles */
}
}
// @media only screen and (min-width: 2500px) {
// .page__home {
// margin: 0 calc(-1 * max(0px, 45vw - 800px)); /* Inverses the magic numbers used in the main layout styles */
// }
// }
+49 -51
View File
@@ -1,54 +1,52 @@
@if ($featured)
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading featured-header">
<h4><i class="{{ config('other.font-awesome') }} fa-star"></i> {{ __('blocks.featured-torrents') }}</h4>
</div>
<div x-data>
<ul
class="featured-carousel"
x-ref="featured"
x-init="setInterval(function () {$el.parentNode.matches(':hover') ? null : (($el.scrollLeft == $el.scrollWidth - $el.offsetWidth - 16) ? $el.scrollLeft = 0 : $el.scrollLeft += (($el.children[0].offsetWidth + 16) / 2 + 1)) }, 5000)"
>
@foreach ($featured as $feature)
@if ($feature->torrent === null || ! $feature->torrent->isApproved())
@continue
@endif
@php
$meta = match(1) {
$feature->torrent->category->tv_meta => App\Models\Tv::query()->with('genres', 'networks', 'seasons')->where('id', '=', $feature->torrent->tmdb ?? 0)->first(),
$feature->torrent->category->movie_meta => App\Models\Movie::query()->with('genres', 'cast', 'companies', 'collection')->where('id', '=', $feature->torrent->tmdb ?? 0)->first(),
$feature->torrent->category->game_meta => MarcReichel\IGDBLaravel\Models\Game::query()->with(['artworks' => ['url', 'image_id'], 'genres' => ['name']])->find((int) $feature->torrent->igdb),
default => null,
};
@endphp
<li class="featured-carousel__slide">
<x-torrent.card :meta="$meta" :torrent="$feature->torrent" />
<footer class="featured-carousel__feature-details">
<p class="featured-carousel__featured-until">
{{ __('blocks.featured-until') }}:<br>
<time datetime="{{ $feature->created_at->addDay(7) }}">
{{ $feature->created_at->addDay(7)->toFormattedDateString() }}
({{ $feature->created_at->addDay(7)->diffForHumans() }}!)
</time>
</p>
<p class="featured-carousel__featured-by">
{{ __('blocks.featured-by') }}: {{ $feature->user->username }}!
</p>
</footer>
</li>
@endforeach
</ul>
<nav class="featured-carousel__nav">
<button class="featured-carousel__previous" x-on:click="$refs.featured.scrollLeft == 0 ? $refs.featured.scrollLeft = $refs.featured.scrollWidth : $refs.featured.scrollLeft -= (($refs.featured.children[0].offsetWidth + 16) / 2 + 1)">
<i class="{{ \config('other.font-awesome') }} fa-angle-left"></i>
</button>
<button class="featured-carousel__next" x-on:click="$refs.featured.scrollLeft == ($refs.featured.scrollWidth - $refs.featured.offsetWidth) ? $refs.featured.scrollLeft = 0 : $refs.featured.scrollLeft += (($refs.featured.children[0].offsetWidth + 16) / 2 + 1)">
<i class="{{ \config('other.font-awesome') }} fa-angle-right"></i>
</button>
</nav>
</div>
<section class="panelV2">
<h2 class="panel__heading">
<i class="{{ config('other.font-awesome') }} fa-star"></i>
{{ __('blocks.featured-torrents') }}
</h2>
<div x-data>
<ul
class="featured-carousel"
x-ref="featured"
{{-- x-init="setInterval(function () {$el.parentNode.matches(':hover') ? null : (($el.scrollLeft == $el.scrollWidth - $el.offsetWidth - 16) ? $el.scrollLeft = 0 : $el.scrollLeft += (($el.children[0].offsetWidth + 16) / 2 + 1)) }, 5000)" --}}
>
@foreach ($featured as $feature)
@if ($feature->torrent === null || ! $feature->torrent->isApproved())
@continue
@endif
@php
$meta = match(1) {
$feature->torrent->category->tv_meta => App\Models\Tv::query()->with('genres', 'networks', 'seasons')->where('id', '=', $feature->torrent->tmdb ?? 0)->first(),
$feature->torrent->category->movie_meta => App\Models\Movie::query()->with('genres', 'cast', 'companies', 'collection')->where('id', '=', $feature->torrent->tmdb ?? 0)->first(),
$feature->torrent->category->game_meta => MarcReichel\IGDBLaravel\Models\Game::query()->with(['artworks' => ['url', 'image_id'], 'genres' => ['name']])->find((int) $feature->torrent->igdb),
default => null,
};
@endphp
<li class="featured-carousel__slide">
<x-torrent.card :meta="$meta" :torrent="$feature->torrent" />
<footer class="featured-carousel__feature-details">
<p class="featured-carousel__featured-until">
{{ __('blocks.featured-until') }}:<br>
<time datetime="{{ $feature->created_at->addDay(7) }}">
{{ $feature->created_at->addDay(7)->toFormattedDateString() }}
({{ $feature->created_at->addDay(7)->diffForHumans() }}!)
</time>
</p>
<p class="featured-carousel__featured-by">
{{ __('blocks.featured-by') }}: {{ $feature->user->username }}!
</p>
</footer>
</li>
@endforeach
</ul>
<nav class="featured-carousel__nav">
<button class="featured-carousel__previous" x-on:click="$refs.featured.scrollLeft == 0 ? $refs.featured.scrollLeft = $refs.featured.scrollWidth : $refs.featured.scrollLeft -= (($refs.featured.children[0].offsetWidth + 16) / 2 + 1)">
<i class="{{ \config('other.font-awesome') }} fa-angle-left"></i>
</button>
<button class="featured-carousel__next" x-on:click="$refs.featured.scrollLeft == ($refs.featured.scrollWidth - $refs.featured.offsetWidth) ? $refs.featured.scrollLeft = 0 : $refs.featured.scrollLeft += (($refs.featured.children[0].offsetWidth + 16) / 2 + 1)">
<i class="{{ \config('other.font-awesome') }} fa-angle-right"></i>
</button>
</nav>
</div>
</div>
</section>
@endif
+20 -39
View File
@@ -1,41 +1,22 @@
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4><i class="{{ config('other.font-awesome') }} fa-comments"></i> {{ __('blocks.latest-posts') }}</h4>
</div>
<div class="table-responsive">
<table class="table table-condensed table-striped table-bordered">
<thead>
<tr>
<th class="torrents-filename">{{ __('forum.post') }}</th>
<th>{{ __('forum.topic') }}</th>
<th>{{ __('forum.author') }}</th>
<th>{{ __('forum.created') }}</th>
</tr>
</thead>
<tbody>
@foreach ($posts as $p)
@if ($p->topic->viewable())
<tr>
<td>
<a
href="{{ route('forum_topic', ['id' => $p->topic->id]) }}?page={{ $p->getPageNumber() }}#post-{{ $p->id }}">{{ preg_replace('#\[[^\]]+\]#', '', Str::limit(htmlspecialchars_decode($p->content)), 75) }}
...</a></td>
<td>{{ $p->topic->name }}</td>
<td>{{ $p->user->username }}</td>
<td>{{ $p->updated_at->diffForHumans() }}</td>
</tr>
@endif
<section class="panelV2">
<header class="panel__header">
<h2 class="panel__heading">
<a href="{{ route('forum_latest_posts') }}">
{{ __('blocks.latest-posts') }}
</a>
</h2>
</header>
<div class="panel__body">
@if ($posts->count() > 0)
<ul class="topic-posts">
@foreach ($posts as $post)
<li class="post-listings__item">
<x-forum.post :post="$post" />
</li>
@endforeach
</tbody>
<thead>
<tr>
<th colspan="4" class="text-right"><a href="{{ route('forum_latest_posts') }}"
class="text-info">{{ __('articles.read-more') }}</a></th>
</tr>
</thead>
</table>
</div>
</ul>
@else
No posts.
@endif
</div>
</div>
</section>
+23 -47
View File
@@ -1,48 +1,24 @@
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4><i class="{{ config('other.font-awesome') }} fa-list-alt"></i> {{ __('blocks.latest-topics') }}</h4>
<section class="panelV2">
<header class="panel__header">
<h2 class="panel__heading">
<a href="{{ route('forum_latest_topics') }}">
{{ __('blocks.latest-topics') }}
</a>
</h2>
</header>
@if($topics->count() > 0)
<ul class="topic-listings">
@foreach ($topics as $topic)
@if ($topic->viewable())
<li class="topic-listings__item">
<x-forum.topic-listing :topic="$topic" />
</li>
@endif
@endforeach
</ul>
@else
<div class="panel__body">
No topics.
</div>
<div class="table-responsive">
<table class="table table-condensed table-striped table-bordered">
<thead>
<tr>
<th class="torrents-filename">{{ __('forum.forum') }}</th>
<th class="torrents-filename">{{ __('forum.topic') }}</th>
<th>{{ __('forum.author') }}</th>
<th>{{ __('forum.created') }}</th>
</tr>
</thead>
<tbody>
@foreach ($topics as $topic)
@if ($topic->viewable())
<tr>
<td>
<a href="{{ route('forums.show', ['id' => $topic->forum->id]) }}">
{{ $topic->forum->name }}
</a>
</td>
<td>
<a href="{{ route('forum_topic', ['id' => $topic->id]) }}">
{{ $topic->name }}
</a>
</td>
<td>{{ $topic->first_post_user_username }}</td>
<td>{{ $topic->created_at->diffForHumans() }}</td>
</tr>
@endif
@endforeach
</tbody>
<thead>
<tr>
<th colspan="4" class="text-right"><a href="{{ route('forum_latest_topics') }}"
class="text-info">{{ __('articles.read-more') }}</a></th>
</tr>
</thead>
</table>
</div>
</div>
</div>
@endif
</section>
+49 -63
View File
@@ -1,67 +1,53 @@
@foreach ($articles as $article)
<div class="col-md-10 col-sm-10 col-md-offset-1">
@if ($article->newNews)
<div class="panel panel-danger">
<div class="panel-heading">
<h4 class="text-center">
<a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#accordion"
href="#collapse4" style="color:#ffffff;">
@joypixels(':rotating_light:') {{ __('blocks.new-news') }} {{ $article->created_at->diffForHumans() }}
@joypixels(':rotating_light:')
</a>
</h4>
</div>
<section class="panelV2" x-data="{ show: {{ $article->newNews }} }">
<header class="panel__header" x-on:click="show = !show" style="cursor: pointer;">
<h2 class="panel__heading panel__heading--centered">
@if ($article->newNews)
@joypixels(':rotating_light:') {{ __('blocks.new-news') }} {{ $article->created_at->diffForHumans() }}
@joypixels(':rotating_light:')
@else
<div class="panel panel-success">
<div class="panel-heading">
<h4 class="text-center">
<a class="accordion-toggle collapsed" data-toggle="collapse" data-parent="#accordion"
href="#collapse4" style="color:#ffffff;">
{{ __('blocks.check-news') }} {{ $article->created_at->diffForHumans() }}
</a>
</h4>
</div>
@endif
<div aria-expanded="{{ ($article->newNews ? 'true' : 'false') }}" id="collapse4"
class="panel-collapse collapse {{ ($article->newNews ? 'in' : '') }}"
style="{{ ($article->newNews ? '' : 'height: 0;') }}">
<div class="panel-body no-padding">
<div class="news-blocks">
<a href="{{ route('articles.show', ['id' => $article->id]) }}"
style=" float: right; margin-right: 10px;">
@if ( ! is_null($article->image))
<img src="{{ url('files/img/' . $article->image) }}"
alt="{{ $article->title }}">
@else
<img src="{{ url('img/missing-image.png') }}" alt="{{ $article->title }}">
@endif
</a>
<h1 class="text-bold" style="display: inline ;">{{ $article->title }}</h1>
<p class="text-muted">
<em>{{ __('articles.published-at') }}
{{ $article->created_at->toDayDateTimeString() }}</em>
</p>
<p style="margin-top: 20px;">
@joypixels(preg_replace('#\[[^\]]+\]#', '', Str::limit($article->content),
150))...
</p>
<a href="{{ route('articles.show', ['id' => $article->id]) }}"
class="btn btn-success">
{{ __('articles.read-more') }}
</a>
<div class="pull-right">
<a href="{{ route('articles.index') }}" class="btn btn-primary">
{{ __('common.view-all') }}
</a>
</div>
</div>
</div>
</div>
</div>
{{ __('blocks.check-news') }} {{ $article->created_at->diffForHumans() }}
@endif
</h2>
<div class="panel__actions">
<div class="panel__action">
<a href="{{ route('articles.index') }}" class="form__button form__button--text">
{{ __('common.view-all') }}
</a>
</div>
</div>
</header>
<div class="panel__body" x-cloak x-show="show">
<article class="article-preview">
<header class="article-preview__header">
<h2 class="article-preview__title">
<a
class="article-preview__link"
href="{{ route('articles.show', ['id' => $article->id]) }}"
>
{{ $article->title }}
</a>
</h2>
<time
class="article-preview__published-date"
datetime="{{ $article->created_at }}"
title="{{ $article->created_at }}"
>
{{ $article->created_at->diffForHumans() }}
</time>
<img
class="article-preview__image"
src="{{ url($article->image ? 'files/img/'.$article->image : 'img/missing-image.png') }}"
alt=""
>
</header>
<p class="article-preview__content">
@joypixels(preg_replace('#\[[^\]]+\]#', '', Str::limit($article->content, 500, '...'), 150))
</p>
<a href="{{ route('articles.show', ['id' => $article->id]) }}" class="article-preview__read-more">
{{ __('articles.read-more') }}
</a>
</article>
</div>
</section>
@endforeach
+37 -56
View File
@@ -1,60 +1,41 @@
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4><i class="{{ config('other.font-awesome') }} fa-users"></i> {{ __('blocks.users-online') }}
<span class="label label-default">{{ $users->count() }}</span>
</h4>
</div>
<div class="panel-body">
<section class="panelV2">
<h2 class="panel__heading">
<i class="{{ config('other.font-awesome') }} fa-users"></i>
{{ __('blocks.users-online') }} ({{ $users->count() }})
</h2>
<div class="panel__body">
<ul style="display: flex; flex-wrap: wrap; column-gap: 1rem; list-style-type: none; padding: 0">
@foreach ($users as $user)
@if ($user->hidden == 1 || !$user->isVisible($user, 'other', 'show_online'))
<span class="badge-user text-orange text-bold" style="margin-bottom: 10px;">
<i class="{{ config('other.font-awesome') }} fa-user-ninja"></i>
{{ strtoupper(__('common.hidden')) }}
@if (auth()->user()->group->is_modo)
<a href="{{ route('users.show', ['username' => $user->username]) }}">
{{ $user->username }}
@if ($user->warnings_count > 0)
<i class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange"
title="{{ __('common.active-warning') }}"></i>
@endif
</a>
<li>
<x-user_tag :user="$user" :anon="$user->hidden || ! $user->isVisible($user, 'other', 'show_online')">
@if ($user->warnings_count > 0)
<x-slot:appended-icons>
<i
class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange"
title="{{ __('common.active-warning') }} ({{ $user->warnings_count }})"
></i>
</x-slot>
@endif
</span>
@else
<a href="{{ route('users.show', ['username' => $user->username]) }}">
<span class="badge-user text-bold"
style="color:{{ $user->group->color }}; background-image:{{ $user->group->effect }}; margin-bottom: 10px;">
<i class="{{ $user->group->icon }}" title="{{ $user->group->name }}"></i>
{{ $user->username }}
@if ($user->warnings_count > 0)
<i class="{{ config('other.font-awesome') }} fa-exclamation-circle text-orange"
title="{{ __('common.active-warning') }}"></i>
@endif
</span>
</a>
@endif
</x-user_tag>
</li>
@endforeach
</div>
<div class="panel-footer">
<div class="row">
<div class="col-sm-12">
<div class="text-center">
<span class="badge-user text-orange text-bold">
<i class="{{ config('other.font-awesome') }} fa-eye-slash" aria-hidden="true"></i>
{{ strtoupper(__('common.hidden')) }}
</span>
@foreach ($groups as $group)
<span class="badge-user text-bold"
style="color:{{ $group->color }}; background-image:{{ $group->effect }};">
<i class="{{ $group->icon }}" aria-hidden="true"></i> {{ $group->name }}
</span>
@endforeach
</div>
</div>
</div>
</div>
</ul>
<hr>
<ul style="display: flex; flex-wrap: wrap; column-gap: 1rem; list-style-type: none; padding: 0; justify-content: center">
@foreach ($groups as $group)
<x-user_tag
:user="(object) [
'username' => $group->name,
'group' => (object) [
'icon' => $group->icon,
'color' => $group->color,
'effect' => $group->effect,
'name' => $group->name,
]
]"
:anon="false"
/>
@endforeach
</ul>
</div>
</div>
</section>
+5 -53
View File
@@ -1,56 +1,8 @@
@if ($poll && $poll->voters->where('user_id', '=', auth()->user()->id)->isEmpty())
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4><i class="{{ config('other.font-awesome') }} fa-chart-pie"></i> {{ __('poll.poll') }}</h4>
</div>
<div class="panel-body">
<h3 class="poll-title">{{ $poll->title }}</h3>
<form class="form-horizontal" method="POST" action="/polls/vote">
@csrf
@if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@csrf
@if ($poll->multiple_choice)
@foreach ($poll->options as $option)
<div class="poll-item">
<label>
<input type="checkbox" name="option[]" value="{{ $option->id }}">
<span class="badge-user">{{ $option->name }}</span>
</label>
</div>
@endforeach
@else
@foreach ($poll->options as $option)
<div class="poll-item">
<label>
<input type="radio" name="option[]" value="{{ $option->id }}" required>
<span class="badge-user">{{ $option->name }}</span>
</label>
</div>
@endforeach
@endif
<div class="poll form-group">
<div class="col-md-12">
<button type="submit" class="btn btn-primary">{{ __('poll.vote') }}</button>
</div>
</div>
</form>
@if ($poll->multiple_choice)
<span class="badge-user text-bold text-red poll-note">{{ __('poll.multiple-choice') }}</span>
@endif
</div>
<section class="panelV2">
<h2 class="panel__heading">{{ __('poll.poll') }}: {{ $poll->title }}</h2>
<div class="panel__body">
@include('poll.forms.vote')
</div>
</div>
</section>
@endif
File diff suppressed because it is too large Load Diff
+64 -146
View File
@@ -1,147 +1,65 @@
<div class="col-md-10 col-sm-10 col-md-offset-1">
<div class="clearfix visible-sm-block"></div>
<div class="panel panel-chat shoutbox">
<div class="panel-heading">
<h4><i class="{{ config('other.font-awesome') }} fa-trophy-alt"></i> {{ __('user.top-uploaders-count') }}</h4>
</div>
<ul class="nav nav-tabs mb-12" role="tablist">
<li class="col-md-6">
<a href="#alltime" role="tab" data-toggle="tab" aria-expanded="true">
<i class="{{ config('other.font-awesome') }} fa-trophy-alt text-gold"></i> {{ __('stat.all-time') }}
</a>
</li>
<li class="active col-md-6">
<a href="#30days" role="tab" data-toggle="tab" aria-expanded="false">
<i class="{{ config('other.font-awesome') }} fa-trophy text-success"></i> {{ __('stat.last30days') }}
</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade" id="alltime">
<div class="table-responsive">
<table class="table table-condensed table-striped table-bordered">
<thead>
<tr>
<th class="torrents-icon"></th>
<th>{{ __('common.user') }}</th>
<th>{{ __('user.total-uploads') }}</th>
<th>{{ __('stat.place') }}</th>
</tr>
</thead>
<tbody>
@foreach ($uploaders as $key => $uploader)
<tr>
<td>
<div class="text-center">
<i
class="{{ config('other.font-awesome') }} fa-trophy-alt text-gold torrent-icon"></i>
</div>
</td>
<td>
@if ($uploader->user->private_profile == 1)
<span class="badge-user text-bold">
<span class="text-orange">
<i class="{{ config('other.font-awesome') }} fa-eye-slash"
aria-hidden="true"></i> {{ strtoupper(__('common.hidden')) }}
</span>
@if ($user->id == $uploader->user->id || $user->group->is_modo == 1)
<a href="{{ route('users.show', ['username' => $uploader->user->username]) }}">
({{ $uploader->user->username }})
</a>
@endif
</span>
@else
<a href="{{ route('users.show', ['username' => $uploader->user->username]) }}">
<span class="badge-user text-bold"
style="color:{{ $uploader->user->group->color }}; background-image:{{ $uploader->user->group->effect }}; margin-bottom: 10px;">
<i class="{{ $uploader->user->group->icon }}" title="{{ $uploader->user->group->name }}"></i>
{{ $uploader->user->username }}
</span>
</a>
@endif
</td>
<td>
<span class="text-green">{{ $uploader->value }}</span>
</td>
<td>
<span class="text-bold"><i
class="{{ config('other.font-awesome') }} fa-ribbon"></i>
{{ App\Helpers\StringHelper::ordinal(++$key) }} {{ __('stat.place') }}</span>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="tab-pane fade active in" id="30days">
<div class="table-responsive">
<table class="table table-condensed table-striped table-bordered">
<thead>
<tr>
<th class="torrents-icon"></th>
<th>{{ __('common.user') }}</th>
<th>{{ __('user.total-uploads') }}</th>
<th>{{ __('stat.place') }}</th>
</tr>
</thead>
<tbody>
@foreach ($past_uploaders as $key => $past_uploader)
<tr>
<td>
<div class="text-center">
<i
class="{{ config('other.font-awesome') }} fa-trophy text-success torrent-icon"></i>
</div>
</td>
<td>
@if ($past_uploader->user->private_profile == 1)
<span class="badge-user text-bold">
<span class="text-orange">
<i class="{{ config('other.font-awesome') }} fa-eye-slash"
aria-hidden="true"></i> {{ strtoupper(__('common.hidden')) }}
</span>
@if ($user->id == $past_uploader->user->id || $user->group->is_modo == 1)
<a
href="{{ route('users.show', ['username' => $past_uploader->user->username]) }}">
({{ $past_uploader->user->username }})
</a>
@endif
</span>
@else
<a href="{{ route('users.show', ['username' => $past_uploader->user->username]) }}">
<span class="badge-user text-bold"
style="color:{{ $past_uploader->user->group->color }}; background-image:{{ $past_uploader->user->group->effect }}; margin-bottom: 10px;">
<i class="{{ $past_uploader->user->group->icon }}"
title="{{ $past_uploader->user->group->name }}"></i>
{{ $past_uploader->user->username }}
</span>
</a>
@endif
</td>
<td>
<span class="text-green">{{ $past_uploader->value }}</span>
</td>
<td>
<span class="text-bold"><i
class="{{ config('other.font-awesome') }} fa-ribbon"></i>
{{ App\Helpers\StringHelper::ordinal(++$key) }} {{ __('stat.place') }}</span>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
<section class="panelV2" x-data="{ tab: 'alltime'}">
<h2 class="panel__heading">{{ __('blocks.top-torrents') }}</h2>
<menu class="panel__tabs">
<li
class="panel__tab"
role="tab"
x-bind:class="tab === 'alltime' && 'panel__tab--active'"
x-on:click="tab = 'alltime'"
>
{{ __('blocks.new-torrents') }}
</li>
<li
class="panel__tab"
role="tab"
x-bind:class="tab === '30days' && 'panel__tab--active'"
x-on:click="tab = '30days'"
>
{{ __('stat.last30days') }}
</li>
</menu>
<div class="data-table-wrapper" x-show="tab === 'alltime'">
<table class="data-table">
<thead>
<tr>
<th>{{ __('common.user') }}</th>
<th>{{ __('user.total-uploads') }}</th>
<th>{{ __('stat.place') }}</th>
</tr>
</thead>
<tbody>
@foreach($uploaders as $uploader)
<tr>
<td>
<x-user_tag :user="$uploader->user" :anon="$uploader->user->private_profile" />
</td>
<td>{{ $uploader->value }}</td>
<td>{{ App\Helpers\StringHelper::ordinal($loop->iteration) }} {{ __('stat.place') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="data-table-wrapper" x-clock x-show="tab === '30days'">
<table class="data-table">
<thead>
<tr>
<th>{{ __('common.user') }}</th>
<th>{{ __('user.total-uploads') }}</th>
<th>{{ __('stat.place') }}</th>
</tr>
</thead>
<tbody>
@foreach($past_uploaders as $uploader)
<tr>
<td>
<x-user_tag :user="$uploader->user" :anon="$uploader->user->private_profile" />
</td>
<td>{{ $uploader->value }}</td>
<td>{{ App\Helpers\StringHelper::ordinal($loop->iteration) }} {{ __('stat.place') }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</section>
+17 -17
View File
@@ -1,22 +1,22 @@
@extends('layout.default')
@section('content')
<div class="page__home">
@include('blocks.news')
@section('page', 'page__home')
@if (!auth()->user()->chat_hidden)
<div id="vue">
<script src="{{ mix('js/chat.js') }}" crossorigin="anonymous"></script>
@include('blocks.chat')
</div>
@endif
@section('main')
@include('blocks.news')
@include('blocks.featured')
@include('blocks.poll')
@include('blocks.top_torrents')
@include('blocks.top_uploaders')
@include('blocks.latest_topics')
@include('blocks.latest_posts')
@include('blocks.online')
</div>
@if (!auth()->user()->chat_hidden)
<div id="vue">
<script src="{{ mix('js/chat.js') }}" crossorigin="anonymous"></script>
@include('blocks.chat')
</div>
@endif
@include('blocks.featured')
@include('blocks.poll')
@include('blocks.top_torrents')
@include('blocks.top_uploaders')
@include('blocks.latest_topics')
@include('blocks.latest_posts')
@include('blocks.online')
@endsection