Skip to content

Commit

Permalink
New landing page design
Browse files Browse the repository at this point in the history
  • Loading branch information
dansup committed Apr 8, 2023
1 parent e7a19b2 commit 09c0032
Show file tree
Hide file tree
Showing 16 changed files with 1,779 additions and 126 deletions.
45 changes: 45 additions & 0 deletions app/Http/Controllers/LandingController.php
@@ -0,0 +1,45 @@
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Profile;
use App\Services\AccountService;
use App\Http\Resources\DirectoryProfile;

class LandingController extends Controller
{
public function directoryRedirect(Request $request)
{
if($request->user()) {
return redirect('/');
}

abort_if(config_cache('landing.show_directory') != 1, 404);

return view('site.index');
}

public function exploreRedirect(Request $request)
{
if($request->user()) {
return redirect('/');
}

abort_if(config_cache('landing.show_explore_feed') != 1, 404);

return view('site.index');
}

public function getDirectoryApi(Request $request)
{
abort_if(config_cache('landing.show_directory') != 1, 404);

return DirectoryProfile::collection(
Profile::whereNull('domain')
->whereIsSuggestable(true)
->orderByDesc('updated_at')
->cursorPaginate(20)
);
}
}
37 changes: 37 additions & 0 deletions app/Http/Resources/DirectoryProfile.php
@@ -0,0 +1,37 @@
<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use Cache;
use App\Services\AccountService;

class DirectoryProfile extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable
*/
public function toArray($request)
{
$account = AccountService::get($this->id, true);
if(!$account) {
return [];
}

$url = url($this->username);
return [
'id' => $this->id,
'name' => $this->name,
'username' => $this->username,
'url' => $url,
'avatar' => $account['avatar'],
'following_count' => $account['following_count'],
'followers_count' => $account['followers_count'],
'statuses_count' => $account['statuses_count'],
'bio' => $account['note_text']
];
}
}
104 changes: 104 additions & 0 deletions app/Services/LandingService.php
@@ -0,0 +1,104 @@
<?php

namespace App\Services;

use App\Util\ActivityPub\Helpers;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use App\Status;
use App\User;
use App\Services\AccountService;

class LandingService
{
public static function get($json = true)
{
$activeMonth = Cache::remember('api:nodeinfo:am', 172800, function() {
return User::select('last_active_at')
->where('last_active_at', '>', now()->subMonths(1))
->orWhere('created_at', '>', now()->subMonths(1))
->count();
});

$totalUsers = Cache::remember('api:nodeinfo:users', 43200, function() {
return User::count();
});

$postCount = Cache::remember('api:nodeinfo:statuses', 21600, function() {
return Status::whereLocal(true)->count();
});

$contactAccount = Cache::remember('api:v1:instance-data:contact', 604800, function () {
$admin = User::whereIsAdmin(true)->first();
return $admin && isset($admin->profile_id) ?
AccountService::getMastodon($admin->profile_id, true) :
null;
});

$rules = Cache::remember('api:v1:instance-data:rules', 604800, function () {
return config_cache('app.rules') ?
collect(json_decode(config_cache('app.rules'), true))
->map(function($rule, $key) {
$id = $key + 1;
return [
'id' => "{$id}",
'text' => $rule
];
})
->toArray() : [];
});

$res = [
'name' => config_cache('app.name'),
'url' => config_cache('app.url'),
'domain' => config('pixelfed.domain.app'),
'show_directory' => config_cache('landing.show_directory') == 1,
'show_explore_feed' => config_cache('landing.show_explore_feed') == 1,
'open_registration' => config_cache('pixelfed.open_registration') == 1,
'version' => config('pixelfed.version'),
'about' => [
'banner_image' => config_cache('app.banner_image') ?? url('/storage/headers/default.jpg'),
'short_description' => config_cache('app.short_description'),
'description' => config_cache('app.description'),
],
'stats' => [
'active_users' => (int) $activeMonth,
'posts_count' => (int) $postCount,
'total_users' => (int) $totalUsers
],
'contact' => [
'account' => $contactAccount,
'email' => config('instance.email')
],
'rules' => $rules,
'uploader' => [
'max_photo_size' => (int) (config('pixelfed.max_photo_size') * 1024),
'max_caption_length' => (int) config('pixelfed.max_caption_length'),
'max_altext_length' => (int) config('pixelfed.max_altext_length', 150),
'album_limit' => (int) config_cache('pixelfed.max_album_length'),
'image_quality' => (int) config_cache('pixelfed.image_quality'),
'max_collection_length' => (int) config('pixelfed.max_collection_length', 18),
'optimize_image' => (bool) config('pixelfed.optimize_image'),
'optimize_video' => (bool) config('pixelfed.optimize_video'),
'media_types' => config_cache('pixelfed.media_types'),
],
'features' => [
'federation' => config_cache('federation.activitypub.enabled'),
'timelines' => [
'local' => true,
'network' => (bool) config('federation.network_timeline'),
],
'mobile_apis' => (bool) config_cache('pixelfed.oauth_enabled'),
'stories' => (bool) config_cache('instance.stories.enabled'),
'video' => Str::contains(config_cache('pixelfed.media_types'), 'video/mp4'),
]
];

if($json) {
return json_encode($res);
}

return $res;
}
}
139 changes: 139 additions & 0 deletions resources/assets/components/landing/Directory.vue
@@ -0,0 +1,139 @@
<template>
<div class="landing-directory-component">
<section class="page-wrapper">
<div class="container container-compact">
<div class="card bg-bluegray-900" style="border-radius: 10px;">
<div class="card-header bg-bluegray-800 nav-menu" style="border-top-left-radius: 10px; border-top-right-radius: 10px;">
<ul class="nav justify-content-around">
<li class="nav-item">
<router-link to="/" class="nav-link">About</router-link>
</li>
<li v-if="config.show_directory" class="nav-item">
<router-link to="/web/directory" class="nav-link">Directory</router-link>
</li>
<li v-if="config.show_explore_feed" class="nav-item">
<router-link to="/web/explore" class="nav-link">Explore</router-link>
</li>
</ul>
</div>

<div class="card-body">
<div class="py-3">
<p class="lead text-center">Discover accounts and people</p>
</div>

<div v-if="loading" class="d-flex justify-content-center align-items-center" style="min-height: 500px;">
<b-spinner />
</div>

<div v-else class="feed-list">
<user-card
v-for="account in feed"
:key="account.id"
:account="account" />

<intersect v-if="canLoadMore && !isEmpty" @enter="enterIntersect">
<div class="d-flex justify-content-center pt-5 pb-3">
<b-spinner v-if="isLoadingMore" />
</div>
</intersect>
</div>

<div v-if="isEmpty">
<div class="card card-body bg-bluegray-800">
<div class="d-flex justify-content-center align-items-center flex-column py-5">
<i class="fal fa-clock fa-6x text-bluegray-500"></i>
<p class="lead font-weight-bold mt-3 mb-0">Nothing to show yet! Check back later.</p>
</div>
</div>
</div>
</div>
</div>
</div>

<footer-component />
</section>
</div>
</template>

<script type="text/javascript">
import UserCard from './partials/UserCard';
import Intersect from 'vue-intersect';
export default {
components: {
"user-card": UserCard,
"intersect": Intersect,
},
data() {
return {
loading: true,
config: window.pfl,
pagination: undefined,
feed: [],
isEmpty: false,
canLoadMore: false,
isIntersecting: false,
isLoadingMore: false
}
},
beforeMount() {
if(this.config.show_directory == false) {
this.$router.push('/');
}
},
mounted() {
this.init();
},
methods: {
init() {
axios.get('/api/landing/v1/directory')
.then(res => {
if(!res.data.data.length) {
this.isEmpty = true;
}
this.feed = res.data.data;
this.pagination = {...res.data.links, ...res.data.meta};
})
.finally(() => {
this.canLoadMore = true;
this.$nextTick(() => {
this.loading = false;
})
})
},
enterIntersect(e) {
if(this.isIntersecting || !this.pagination.next_cursor) {
return;
}
this.isIntersecting = true;
this.isLoadingMore = true;
axios.get('/api/landing/v1/directory', {
params: {
cursor: this.pagination.next_cursor
}
})
.then(res => {
this.feed.push(...res.data.data);
this.pagination = {...res.data.links, ...res.data.meta};
})
.finally(() => {
if(this.pagination.next_cursor) {
this.canLoadMore = true;
} else {
this.canLoadMore = false;
}
this.isLoadingMore = false;
this.isIntersecting = false;
});
console.log(e);
}
}
}
</script>

0 comments on commit 09c0032

Please sign in to comment.