mirror of
https://github.com/YunoHost-Apps/pixelfed_ynh.git
synced 2024-09-03 20:06:04 +02:00
commit
e3f16c8b16
47 changed files with 890 additions and 241 deletions
|
@ -4,6 +4,8 @@
|
|||
|
||||
### Added
|
||||
- Added drafts API endpoint for Camera Roll ([bad2ecde](https://github.com/pixelfed/pixelfed/commit/bad2ecde))
|
||||
- Added AccountService ([885a1258](https://github.com/pixelfed/pixelfed/commit/885a1258))
|
||||
- Added post embeds ([1fecf717](https://github.com/pixelfed/pixelfed/commit/1fecf717))
|
||||
|
||||
### Fixed
|
||||
- Fixed like and share/reblog count on profiles ([86cb7d09](https://github.com/pixelfed/pixelfed/commit/86cb7d09))
|
||||
|
@ -45,6 +47,10 @@
|
|||
- Updated StatusTransformer, added ```local``` attribute ([484bb509](https://github.com/pixelfed/pixelfed/commit/484bb509))
|
||||
- Updated PostComponent, fix bug affecting MomentUI and non authenticated users ([7b3fe215](https://github.com/pixelfed/pixelfed/commit/7b3fe215))
|
||||
- Updated FixUsernames command to allow usernames containing ```.``` ([e5d77c6d](https://github.com/pixelfed/pixelfed/commit/e5d77c6d))
|
||||
- Updated landing page, add age check ([d11e82c3](https://github.com/pixelfed/pixelfed/commit/d11e82c3))
|
||||
- Updated ApiV1Controller, add ```mobile_apis``` to /api/v1/instance endpoint ([57407463](https://github.com/pixelfed/pixelfed/commit/57407463))
|
||||
- Updated PublicTimelineService, add video media scopes ([7b00eba3](https://github.com/pixelfed/pixelfed/commit/7b00eba3))
|
||||
- Updated PublicApiController, add AccountService ([5ebd2c8a](https://github.com/pixelfed/pixelfed/commit/5ebd2c8a))
|
||||
|
||||
## Deprecated
|
||||
|
||||
|
|
|
@ -906,7 +906,9 @@ class ApiV1Controller extends Controller
|
|||
'max_avatar_size' => config('pixelfed.max_avatar_size'),
|
||||
'max_caption_length' => config('pixelfed.max_caption_length'),
|
||||
'max_bio_length' => config('pixelfed.max_bio_length'),
|
||||
'max_album_length' => config('pixelfed.max_album_length')
|
||||
'max_album_length' => config('pixelfed.max_album_length'),
|
||||
'mobile_apis' => config('pixelfed.oauth_enabled')
|
||||
|
||||
]
|
||||
];
|
||||
return response()->json($res, 200, [], JSON_PRETTY_PRINT);
|
||||
|
|
|
@ -63,7 +63,7 @@ class RegisterController extends Controller
|
|||
'unique:users',
|
||||
function ($attribute, $value, $fail) {
|
||||
if (!ctype_alpha($value[0])) {
|
||||
return $fail('Username is invalid. Username must be alpha-numeric and start with a letter.');
|
||||
return $fail('Username is invalid. Must start with a letter or number.');
|
||||
}
|
||||
$val = str_replace(['_', '-', '.'], '', $value);
|
||||
if(!ctype_alnum($val)) {
|
||||
|
@ -73,6 +73,7 @@ class RegisterController extends Controller
|
|||
];
|
||||
|
||||
$rules = [
|
||||
'agecheck' => 'required|accepted',
|
||||
'name' => 'nullable|string|max:'.config('pixelfed.max_name_length'),
|
||||
'username' => $usernameRules,
|
||||
'email' => 'required|string|email|max:255|unique:users',
|
||||
|
|
|
@ -14,6 +14,8 @@ use App\{
|
|||
};
|
||||
use Auth, DB, Cache;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Transformer\Api\AccountTransformer;
|
||||
use App\Transformer\Api\AccountWithStatusesTransformer;
|
||||
use App\Transformer\Api\StatusStatelessTransformer;
|
||||
use League\Fractal;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
|
@ -131,7 +133,31 @@ class DiscoverController extends Controller
|
|||
|
||||
public function profilesDirectory(Request $request)
|
||||
{
|
||||
$profiles = Profile::whereNull('domain')->simplePaginate(48);
|
||||
return view('discover.profiles.home', compact('profiles'));
|
||||
return view('discover.profiles.home');
|
||||
}
|
||||
|
||||
public function profilesDirectoryApi(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'page' => 'integer|max:10'
|
||||
]);
|
||||
|
||||
$page = $request->input('page') ?? 1;
|
||||
$key = 'discover:profiles:page:' . $page;
|
||||
$ttl = now()->addHours(12);
|
||||
|
||||
$res = Cache::remember($key, $ttl, function() {
|
||||
$profiles = Profile::whereNull('domain')
|
||||
->whereNull('status')
|
||||
->whereIsPrivate(false)
|
||||
->has('statuses')
|
||||
->whereIsSuggestable(true)
|
||||
// ->inRandomOrder()
|
||||
->simplePaginate(8);
|
||||
$resource = new Fractal\Resource\Collection($profiles, new AccountTransformer());
|
||||
return $this->fractal->createData($resource)->toArray();
|
||||
});
|
||||
|
||||
return $res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@ use App\Transformer\Api\{
|
|||
RelationshipTransformer,
|
||||
StatusTransformer,
|
||||
};
|
||||
use App\Services\UserFilterService;
|
||||
use App\Services\{
|
||||
AccountService,
|
||||
PublicTimelineService,
|
||||
UserFilterService
|
||||
};
|
||||
use App\Jobs\StatusPipeline\NewStatusPipeline;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
|
@ -38,17 +42,12 @@ class PublicApiController extends Controller
|
|||
$this->fractal->setSerializer(new ArraySerializer());
|
||||
}
|
||||
|
||||
protected function getUserData()
|
||||
protected function getUserData($user)
|
||||
{
|
||||
if(false == Auth::check()) {
|
||||
if(!$user) {
|
||||
return [];
|
||||
} else {
|
||||
$profile = Auth::user()->profile;
|
||||
if($profile->status) {
|
||||
return [];
|
||||
}
|
||||
$user = new Fractal\Resource\Item($profile, new AccountTransformer());
|
||||
return $this->fractal->createData($user)->toArray();
|
||||
return AccountService::get($user->profile_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +89,7 @@ class PublicApiController extends Controller
|
|||
$item = new Fractal\Resource\Item($status, new StatusTransformer());
|
||||
$res = [
|
||||
'status' => $this->fractal->createData($item)->toArray(),
|
||||
'user' => $this->getUserData(),
|
||||
'user' => $this->getUserData($request->user()),
|
||||
'likes' => $this->getLikes($status),
|
||||
'shares' => $this->getShares($status),
|
||||
'reactions' => [
|
||||
|
@ -235,12 +234,13 @@ class PublicApiController extends Controller
|
|||
$max = $request->input('max_id');
|
||||
$limit = $request->input('limit') ?? 3;
|
||||
|
||||
// $private = Cache::remember('profiles:private', now()->addMinutes(1440), function() {
|
||||
// return Profile::whereIsPrivate(true)
|
||||
// ->orWhere('unlisted', true)
|
||||
// ->orWhere('status', '!=', null)
|
||||
// ->pluck('id');
|
||||
// });
|
||||
$private = Cache::remember('profiles:private', now()->addMinutes(1440), function() {
|
||||
return Profile::whereIsPrivate(true)
|
||||
->orWhere('unlisted', true)
|
||||
->orWhere('status', '!=', null)
|
||||
->pluck('id')
|
||||
->toArray();
|
||||
});
|
||||
|
||||
// if(Auth::check()) {
|
||||
// // $pid = Auth::user()->profile->id;
|
||||
|
@ -255,7 +255,17 @@ class PublicApiController extends Controller
|
|||
// $filtered = [];
|
||||
// }
|
||||
|
||||
$filtered = Auth::check() ? UserFilterService::filters(Auth::user()->profile_id) : [];
|
||||
$filtered = Auth::check() ? array_merge($private, UserFilterService::filters(Auth::user()->profile_id)) : [];
|
||||
// if($max == 0) {
|
||||
// $res = PublicTimelineService::count();
|
||||
// if($res == 0) {
|
||||
// PublicTimelineService::warmCache();
|
||||
// $res = PublicTimelineService::get(0,4);
|
||||
// } else {
|
||||
// $res = PublicTimelineService::get(0,4);
|
||||
// }
|
||||
// return response()->json($res);
|
||||
// }
|
||||
|
||||
if($min || $max) {
|
||||
$dir = $min ? '>' : '<';
|
||||
|
@ -321,7 +331,6 @@ class PublicApiController extends Controller
|
|||
|
||||
$fractal = new Fractal\Resource\Collection($timeline, new StatusTransformer());
|
||||
$res = $this->fractal->createData($fractal)->toArray();
|
||||
// $res = $timeline;
|
||||
return response()->json($res);
|
||||
|
||||
}
|
||||
|
@ -439,98 +448,7 @@ class PublicApiController extends Controller
|
|||
|
||||
public function networkTimelineApi(Request $request)
|
||||
{
|
||||
if(!Auth::check()) {
|
||||
return abort(403);
|
||||
}
|
||||
|
||||
$this->validate($request,[
|
||||
'page' => 'nullable|integer|max:40',
|
||||
'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
||||
'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX,
|
||||
'limit' => 'nullable|integer|max:20'
|
||||
]);
|
||||
|
||||
$page = $request->input('page');
|
||||
$min = $request->input('min_id');
|
||||
$max = $request->input('max_id');
|
||||
$limit = $request->input('limit') ?? 3;
|
||||
|
||||
// TODO: Use redis for timelines
|
||||
// $timeline = Timeline::build()->local();
|
||||
$pid = Auth::user()->profile->id;
|
||||
|
||||
$private = Cache::remember('profiles:private', now()->addMinutes(1440), function() {
|
||||
return Profile::whereIsPrivate(true)
|
||||
->orWhere('unlisted', true)
|
||||
->orWhere('status', '!=', null)
|
||||
->pluck('id');
|
||||
});
|
||||
$filters = UserFilter::whereUserId($pid)
|
||||
->whereFilterableType('App\Profile')
|
||||
->whereIn('filter_type', ['mute', 'block'])
|
||||
->pluck('filterable_id')->toArray();
|
||||
$filtered = array_merge($private->toArray(), $filters);
|
||||
|
||||
if($min || $max) {
|
||||
$dir = $min ? '>' : '<';
|
||||
$id = $min ?? $max;
|
||||
$timeline = Status::select(
|
||||
'id',
|
||||
'uri',
|
||||
'caption',
|
||||
'rendered',
|
||||
'profile_id',
|
||||
'type',
|
||||
'in_reply_to_id',
|
||||
'reblog_of_id',
|
||||
'is_nsfw',
|
||||
'scope',
|
||||
'local',
|
||||
'reply_count',
|
||||
'comments_disabled',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
)->where('id', $dir, $id)
|
||||
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album'])
|
||||
->whereNotIn('profile_id', $filtered)
|
||||
->whereNotNull('uri')
|
||||
->whereNull('in_reply_to_id')
|
||||
->whereNull('reblog_of_id')
|
||||
->whereVisibility('public')
|
||||
->latest()
|
||||
->limit($limit)
|
||||
->get();
|
||||
} else {
|
||||
$timeline = Status::select(
|
||||
'id',
|
||||
'uri',
|
||||
'caption',
|
||||
'rendered',
|
||||
'profile_id',
|
||||
'type',
|
||||
'in_reply_to_id',
|
||||
'reblog_of_id',
|
||||
'is_nsfw',
|
||||
'scope',
|
||||
'local',
|
||||
'reply_count',
|
||||
'comments_disabled',
|
||||
'created_at',
|
||||
'updated_at'
|
||||
)->whereIn('type', ['photo', 'photo:album', 'video', 'video:album'])
|
||||
->whereNotIn('profile_id', $filtered)
|
||||
->whereNull('in_reply_to_id')
|
||||
->whereNull('reblog_of_id')
|
||||
->whereNotNull('uri')
|
||||
->whereVisibility('public')
|
||||
->latest()
|
||||
->simplePaginate($limit);
|
||||
}
|
||||
|
||||
$fractal = new Fractal\Resource\Collection($timeline, new StatusTransformer());
|
||||
$res = $this->fractal->createData($fractal)->toArray();
|
||||
return response()->json($res);
|
||||
|
||||
return response()->json([]);
|
||||
}
|
||||
|
||||
public function relationships(Request $request)
|
||||
|
@ -555,10 +473,7 @@ class PublicApiController extends Controller
|
|||
|
||||
public function account(Request $request, $id)
|
||||
{
|
||||
$profile = Profile::whereNull('status')->findOrFail($id);
|
||||
$resource = new Fractal\Resource\Item($profile, new AccountTransformer());
|
||||
$res = $this->fractal->createData($resource)->toArray();
|
||||
|
||||
$res = AccountService::get($id);
|
||||
return response()->json($res);
|
||||
}
|
||||
|
||||
|
|
20
app/Http/Controllers/SeasonalController.php
Normal file
20
app/Http/Controllers/SeasonalController.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Auth;
|
||||
|
||||
class SeasonalController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth');
|
||||
}
|
||||
|
||||
public function yearInReview()
|
||||
{
|
||||
$profile = Auth::user()->profile;
|
||||
return view('account.yir', compact('profile'));
|
||||
}
|
||||
}
|
|
@ -10,10 +10,10 @@ use App\Util\Localization\Localization;
|
|||
|
||||
class SiteController extends Controller
|
||||
{
|
||||
public function home()
|
||||
public function home(Request $request)
|
||||
{
|
||||
if (Auth::check()) {
|
||||
return $this->homeTimeline();
|
||||
return $this->homeTimeline($request);
|
||||
} else {
|
||||
return $this->homeGuest();
|
||||
}
|
||||
|
@ -24,9 +24,13 @@ class SiteController extends Controller
|
|||
return view('site.index');
|
||||
}
|
||||
|
||||
public function homeTimeline()
|
||||
public function homeTimeline(Request $request)
|
||||
{
|
||||
return view('timeline.home');
|
||||
$this->validate($request, [
|
||||
'layout' => 'nullable|string|in:grid,feed'
|
||||
]);
|
||||
$layout = $request->input('layout', 'feed');
|
||||
return view('timeline.home', compact('layout'));
|
||||
}
|
||||
|
||||
public function changeLocale(Request $request, $locale)
|
||||
|
|
|
@ -51,6 +51,12 @@ class StatusController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if($status->type == 'archived') {
|
||||
if(Auth::user()->profile_id !== $status->profile_id) {
|
||||
abort(404);
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->wantsJson() && config('federation.activitypub.enabled')) {
|
||||
return $this->showActivityPub($request, $status);
|
||||
}
|
||||
|
@ -70,13 +76,29 @@ class StatusController extends Controller
|
|||
|
||||
public function showEmbed(Request $request, $username, int $id)
|
||||
{
|
||||
abort(404);
|
||||
$profile = Profile::whereNull('status')->whereUsername($username)->first();
|
||||
$status = Status::whereScope('private')->find($id);
|
||||
if(!$profile || !$status) {
|
||||
return view('status.embed-removed');
|
||||
$profile = Profile::whereNull(['domain','status'])
|
||||
->whereIsPrivate(false)
|
||||
->whereUsername($username)
|
||||
->first();
|
||||
if(!$profile) {
|
||||
$content = view('status.embed-removed');
|
||||
return response($content)->header('X-Frame-Options', 'ALLOWALL');
|
||||
}
|
||||
return view('status.embed', compact('status'));
|
||||
$status = Status::whereProfileId($profile->id)
|
||||
->whereNull('uri')
|
||||
->whereScope('public')
|
||||
->whereIsNsfw(false)
|
||||
->whereIn('type', ['photo', 'video'])
|
||||
->find($id);
|
||||
if(!$status) {
|
||||
$content = view('status.embed-removed');
|
||||
return response($content)->header('X-Frame-Options', 'ALLOWALL');
|
||||
}
|
||||
$showLikes = $request->filled('likes') && $request->likes == true;
|
||||
$showCaption = $request->filled('caption') && $request->caption !== false;
|
||||
$layout = $request->filled('layout') && $request->layout == 'compact' ? 'compact' : 'full';
|
||||
$content = view('status.embed', compact('status', 'showLikes', 'showCaption', 'layout'));
|
||||
return response($content)->withHeaders(['X-Frame-Options' => 'ALLOWALL']);
|
||||
}
|
||||
|
||||
public function showObject(Request $request, $username, int $id)
|
||||
|
|
|
@ -29,6 +29,7 @@ class Kernel extends HttpKernel
|
|||
protected $middlewareGroups = [
|
||||
'web' => [
|
||||
\App\Http\Middleware\EncryptCookies::class,
|
||||
\App\Http\Middleware\FrameGuard::class,
|
||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
|
|
26
app/Http/Middleware/FrameGuard.php
Normal file
26
app/Http/Middleware/FrameGuard.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class FrameGuard
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
if (!$response->headers->has('X-Frame-Options')) {
|
||||
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
29
app/Services/AccountService.php
Normal file
29
app/Services/AccountService.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Cache;
|
||||
use App\Profile;
|
||||
use App\Transformer\Api\AccountTransformer;
|
||||
use League\Fractal;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
|
||||
class AccountService {
|
||||
|
||||
const CACHE_KEY = 'pf:services:account:';
|
||||
|
||||
public static function get($id)
|
||||
{
|
||||
$key = self::CACHE_KEY . ':' . $id;
|
||||
$ttl = now()->addHours(12);
|
||||
|
||||
return Cache::remember($key, $ttl, function() use($id) {
|
||||
$fractal = new Fractal\Manager();
|
||||
$fractal->setSerializer(new ArraySerializer());
|
||||
$profile = Profile::whereNull('status')->findOrFail($id);
|
||||
$resource = new Fractal\Resource\Item($profile, new AccountTransformer());
|
||||
return $fractal->createData($resource)->toArray();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -52,7 +52,7 @@ class PublicTimelineService {
|
|||
$ids = Status::whereNull('uri')
|
||||
->whereNull('in_reply_to_id')
|
||||
->whereNull('reblog_of_id')
|
||||
->whereIn('type', ['photo', 'photo:album'])
|
||||
->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])
|
||||
->whereScope('public')
|
||||
->latest()
|
||||
->limit($limit)
|
||||
|
|
|
@ -33,6 +33,7 @@ class AccountTransformer extends Fractal\TransformerAbstract
|
|||
'website' => $profile->website,
|
||||
'local' => (bool) $local,
|
||||
'is_admin' => (bool) $is_admin,
|
||||
'created_at' => $profile->created_at->timestamp
|
||||
];
|
||||
}
|
||||
|
||||
|
|
56
app/Transformer/Api/AccountWithStatusesTransformer.php
Normal file
56
app/Transformer/Api/AccountWithStatusesTransformer.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace App\Transformer\Api;
|
||||
|
||||
use Auth;
|
||||
use App\Profile;
|
||||
use League\Fractal;
|
||||
|
||||
class AccountWithStatusesTransformer extends Fractal\TransformerAbstract
|
||||
{
|
||||
protected $defaultIncludes = [
|
||||
// 'relationship',
|
||||
'posts',
|
||||
];
|
||||
|
||||
public function transform(Profile $profile)
|
||||
{
|
||||
$local = $profile->domain == null;
|
||||
$is_admin = !$local ? false : $profile->user->is_admin;
|
||||
$acct = $local ? $profile->username : substr($profile->username, 1);
|
||||
$username = $local ? $profile->username : explode('@', $acct)[0];
|
||||
return [
|
||||
'id' => (string) $profile->id,
|
||||
'username' => $username,
|
||||
'acct' => $acct,
|
||||
'display_name' => $profile->name,
|
||||
'locked' => (bool) $profile->is_private,
|
||||
'followers_count' => $profile->followerCount(),
|
||||
'following_count' => $profile->followingCount(),
|
||||
'statuses_count' => (int) $profile->statusCount(),
|
||||
'note' => $profile->bio ?? '',
|
||||
'url' => $profile->url(),
|
||||
'avatar' => $profile->avatarUrl(),
|
||||
'website' => $profile->website,
|
||||
'local' => (bool) $local,
|
||||
'is_admin' => (bool) $is_admin,
|
||||
'created_at' => $profile->created_at->timestamp
|
||||
];
|
||||
}
|
||||
|
||||
protected function includePosts(Profile $profile)
|
||||
{
|
||||
$posts = $profile
|
||||
->statuses()
|
||||
->whereIsNsfw(false)
|
||||
->whereType('photo')
|
||||
->whereScope('public')
|
||||
->whereNull('in_reply_to_id')
|
||||
->whereNull('reblog_of_id')
|
||||
->latest()
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
return $this->collection($posts, new StatusStatelessTransformer());
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ class StatusStatelessTransformer extends Fractal\TransformerAbstract
|
|||
'thread' => false,
|
||||
'replies' => [],
|
||||
'parent' => $status->parent() ? $this->transform($status->parent()) : [],
|
||||
'local' => (bool) $status->local,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
2
public/css/appdark.css
vendored
2
public/css/appdark.css
vendored
File diff suppressed because one or more lines are too long
2
public/css/landing.css
vendored
2
public/css/landing.css
vendored
File diff suppressed because one or more lines are too long
1
public/embed.js
vendored
Normal file
1
public/embed.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!function(){var e;e=function(){var e=[];window.addEventListener("message",function(t){var n=t.data||{};"setHeight"===n.type&&e[n.id]&&(e[n.id].height=n.height)}),[].forEach.call(document.querySelectorAll("iframe.pixelfed__embed"),function(t){t.scrolling="no",t.style.overflow="hidden",e.push(t);var n=e.length-1;t.onload=function(){t.contentWindow.postMessage({type:"setHeight",id:n},"*")},t.onload()})},-1!==["interactive","complete"].indexOf(document.readyState)?e():document.addEventListener("DOMContentLoaded",e)}();
|
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/compose.js
vendored
2
public/js/compose.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/discover.js
vendored
2
public/js/discover.js
vendored
File diff suppressed because one or more lines are too long
1
public/js/profile-directory.js
vendored
Normal file
1
public/js/profile-directory.js
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{19:function(t,e,s){t.exports=s("ETg6")},"7wkd":function(t,e,s){"use strict";s.r(e);var o={props:["profileId"],data:function(){return{loaded:!1,showLoadMore:!0,profiles:[],page:1}},beforeMount:function(){this.fetchData()},methods:{fetchData:function(){var t=this;axios.get("/api/pixelfed/v2/discover/profiles",{params:{page:this.page}}).then(function(e){if(0==e.data.length)return t.showLoadMore=!1,void(t.loaded=!0);t.profiles=e.data,t.showLoadMore=8==t.profiles.length,t.loaded=!0})},prettyCount:function(t){return App.util.format.count(t)},loadMore:function(){this.loaded=!1,this.page++,this.fetchData()},thumbUrl:function(t){return t.media_attachments[0].url},postsPerDay:function(t){var e=t.created_at,s=Date.now(),o=Math.abs(e,s),a=Math.round(o/864e5),n=t.statuses_count,r=this.prettyCount(Math.floor(n/a));return console.log(r),r}}},a=s("KHd+"),n=Object(a.a)(o,function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",[s("div",{staticClass:"col-12"},[s("p",{staticClass:"font-weight-bold text-lighter text-uppercase"},[t._v("Profiles Directory")]),t._v(" "),t.loaded?s("div",{},[s("div",{staticClass:"row"},[t._l(t.profiles,function(e,o){return s("div",{staticClass:"col-12 col-md-6 p-1"},[s("div",{staticClass:"card card-body border shadow-none py-2"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"rounded-circle border mr-3",attrs:{src:e.avatar,alt:"...",width:"40px",height:"40px"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mt-0 mb-0 font-weight-bold"},[s("a",{staticClass:"text-dark",attrs:{href:e.url}},[t._v(t._s(e.username))])]),t._v(" "),s("p",{staticClass:"mb-1 small text-lighter d-flex justify-content-between font-weight-bold"},[s("span",[s("span",[t._v(t._s(t.prettyCount(e.statuses_count)))]),t._v(" POSTS\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.postsPerDay(e)))]),t._v(" POSTS/DAY\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("span",[s("span",[t._v(t._s(t.prettyCount(e.followers_count)))]),t._v(" FOLLOWERS\n\t\t\t\t\t\t\t\t\t")])]),t._v(" "),s("p",{staticClass:"mb-1"},t._l(e.posts,function(e,o){return s("span",{key:"profile_posts_"+o,staticClass:"shadow-sm"},[s("a",{staticClass:"text-decoration-none mr-1",attrs:{href:e.url}},[s("img",{staticClass:"border rounded",attrs:{src:t.thumbUrl(e),width:"62.3px",height:"62.3px"}})])])}),0)])])])])}),t._v(" "),t.showLoadMore?s("div",{staticClass:"col-12"},[s("p",{staticClass:"text-center mb-0 pt-3"},[s("button",{staticClass:"btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold",on:{click:function(e){return t.loadMore()}}},[t._v("Load More")])])]):t._e()],2)]):s("div",[t._m(0)])])])},[function(){var t=this.$createElement,e=this._self._c||t;return e("div",{staticClass:"row"},[e("div",{staticClass:"col-12 d-flex justify-content-center align-items-center"},[e("div",{staticClass:"spinner-border",attrs:{role:"status"}},[e("span",{staticClass:"sr-only"},[this._v("Loading...")])])])])}],!1,null,"76ea0b14",null);e.default=n.exports},ETg6:function(t,e,s){Vue.component("profile-directory",s("7wkd").default)},"KHd+":function(t,e,s){"use strict";function o(t,e,s,o,a,n,r,i){var c,d="function"==typeof t?t.options:t;if(e&&(d.render=e,d.staticRenderFns=s,d._compiled=!0),o&&(d.functional=!0),n&&(d._scopeId="data-v-"+n),r?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),a&&a.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(r)},d._ssrRegister=c):a&&(c=i?function(){a.call(this,this.$root.$options.shadowRoot)}:a),c)if(d.functional){d._injectStyles=c;var l=d.render;d.render=function(t,e){return c.call(e),l(t,e)}}else{var u=d.beforeCreate;d.beforeCreate=u?[].concat(u,c):[c]}return{exports:t,options:d}}s.d(e,"a",function(){return o})}},[[19,0]]]);
|
2
public/js/quill.js
vendored
2
public/js/quill.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/search.js
vendored
2
public/js/search.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/status.js
vendored
2
public/js/status.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/theme-monokai.js
vendored
2
public/js/theme-monokai.js
vendored
|
@ -1 +1 @@
|
|||
(window.webpackJsonp=window.webpackJsonp||[]).push([[19],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
||||
(window.webpackJsonp=window.webpackJsonp||[]).push([[20],{15:function(e,a,o){e.exports=o("YMO/")},"YMO/":function(e,a,o){(function(e){function o(e){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,a,o){a.isDark=!0,a.cssClass="ace-monokai",a.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {color: #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_punctuation,.ace-monokai .ace_punctuation.ace_tag {color: #fff}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y}",e("../lib/dom").importCssString(a.cssText,a.cssClass)}),ace.require(["ace/theme/monokai"],function(c){"object"==o(e)&&"object"==o(a)&&e&&(e.exports=c)})}).call(this,o("YuTi")(e))},YuTi:function(e,a){e.exports=function(e){return e.webpackPolyfill||(e.deprecate=function(){},e.paths=[],e.children||(e.children=[]),Object.defineProperty(e,"loaded",{enumerable:!0,get:function(){return e.l}}),Object.defineProperty(e,"id",{enumerable:!0,get:function(){return e.i}}),e.webpackPolyfill=1),e}}},[[15,0]]]);
|
2
public/js/timeline.js
vendored
2
public/js/timeline.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/vendor.js
vendored
2
public/js/vendor.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,27 +1,28 @@
|
|||
{
|
||||
"/js/manifest.js": "/js/manifest.js?id=01c8731923a46c30aaed",
|
||||
"/js/vendor.js": "/js/vendor.js?id=fac92a458473b287c543",
|
||||
"/js/vendor.js": "/js/vendor.js?id=d8961ac0607442eab9a9",
|
||||
"/js/ace.js": "/js/ace.js?id=585114d8896dc0c24020",
|
||||
"/js/activity.js": "/js/activity.js?id=713d9542e71e87fb88c0",
|
||||
"/js/app.js": "/js/app.js?id=e247f50c24aaed688cc9",
|
||||
"/css/app.css": "/css/app.css?id=67a82ced484bdb354748",
|
||||
"/css/appdark.css": "/css/appdark.css?id=b0fdec1caa1ce13301c6",
|
||||
"/css/landing.css": "/css/landing.css?id=66d18d3f53fa9d41033c",
|
||||
"/js/app.js": "/js/app.js?id=f41aca7673d153a72c21",
|
||||
"/css/app.css": "/css/app.css?id=d3f863cc7a1fd51c10db",
|
||||
"/css/appdark.css": "/css/appdark.css?id=def8c4e280919a0d1453",
|
||||
"/css/landing.css": "/css/landing.css?id=1a9fb68495fe92338bb2",
|
||||
"/css/quill.css": "/css/quill.css?id=711b2150d518816d6112",
|
||||
"/js/collectioncompose.js": "/js/collectioncompose.js?id=b27e524d161917a9e9e1",
|
||||
"/js/collections.js": "/js/collections.js?id=dcc75eec0b3e0736e5fe",
|
||||
"/js/components.js": "/js/components.js?id=be8c9e1c6c52db778f29",
|
||||
"/js/compose.js": "/js/compose.js?id=2d3e96bd3197d49cfe88",
|
||||
"/js/compose.js": "/js/compose.js?id=3e8264e6f459adeb5b49",
|
||||
"/js/compose-classic.js": "/js/compose-classic.js?id=e7483681a575c190a43b",
|
||||
"/js/developers.js": "/js/developers.js?id=9636d4060ca6b359d8a2",
|
||||
"/js/discover.js": "/js/discover.js?id=fbc49123fc2ce2ff7acf",
|
||||
"/js/discover.js": "/js/discover.js?id=ec4f53b810977ff041ae",
|
||||
"/js/hashtag.js": "/js/hashtag.js?id=3fe97ed3f975f0e0baa5",
|
||||
"/js/loops.js": "/js/loops.js?id=9c31302552d789d5f35b",
|
||||
"/js/mode-dot.js": "/js/mode-dot.js?id=993d7fee684361edddbc",
|
||||
"/js/profile.js": "/js/profile.js?id=97bec372a25ffd2e909e",
|
||||
"/js/quill.js": "/js/quill.js?id=37962cd45a252d2f13c9",
|
||||
"/js/search.js": "/js/search.js?id=f312959df65e86a307a3",
|
||||
"/js/status.js": "/js/status.js?id=6fe82a7ab606a7b8740d",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=700e5dc735365e184e41",
|
||||
"/js/timeline.js": "/js/timeline.js?id=e45ea0de04ac33768c74"
|
||||
"/js/profile-directory.js": "/js/profile-directory.js?id=d7d5cb12523cd6bac967",
|
||||
"/js/quill.js": "/js/quill.js?id=d909fb9ece981d98eff1",
|
||||
"/js/search.js": "/js/search.js?id=45c2ede55c2ac48cf1d6",
|
||||
"/js/status.js": "/js/status.js?id=5cdd90acab635eb3fe58",
|
||||
"/js/theme-monokai.js": "/js/theme-monokai.js?id=efa54f8ee94778885eb7",
|
||||
"/js/timeline.js": "/js/timeline.js?id=cdab37b19c377c04acdc"
|
||||
}
|
||||
|
|
20
resources/assets/js/app.js
vendored
20
resources/assets/js/app.js
vendored
|
@ -76,7 +76,21 @@ window.App.util = {
|
|||
['Walden','filter-walden'],
|
||||
['Willow','filter-willow'],
|
||||
['X-Pro II','filter-xpro-ii']
|
||||
],
|
||||
emoji: ['😂','💯','❤️','🙌','👏','👌','😍','😯','😢','😅','😁','🙂','😎','😀','🤣','😃','😄','😆','😉','😊','😋','😘','😗','😙','😚','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😪','😫','😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','🙁','😖','😞','😟','😤','😭','😦','😧','😨','😩','🤯','😬','😰','😱','😳','🤪','😵','😡','😠','🤬','😷','🤒','🤕','🤢','🤮','🤧','😇','🤠','🤡','🤥','🤫','🤭','🧐','🤓','😈','👿','👹','👺','💀','👻','👽','🤖','💩','😺','😸','😹','😻','😼','😽','🙀','😿','😾','🤲','👐','🤝','👍','👎','👊','✊','🤛','🤜','🤞','✌️','🤟','🤘','👈','👉','👆','👇','☝️','✋','🤚','🖐','🖖','👋','🤙','💪','🖕','✍️','🙏','💍','💄','💋','👄','👅','👂','👃','👣','👁','👀','🧠','🗣','👤','👥'
|
||||
],
|
||||
],
|
||||
emoji: ['😂','💯','❤️','🙌','👏','👌','😍','😯','😢','😅','😁','🙂','😎','😀','🤣','😃','😄','😆','😉','😊','😋','😘','😗','😙','😚','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😪','😫','😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','🙁','😖','😞','😟','😤','😭','😦','😧','😨','😩','🤯','😬','😰','😱','😳','🤪','😵','😡','😠','🤬','😷','🤒','🤕','🤢','🤮','🤧','😇','🤠','🤡','🤥','🤫','🤭','🧐','🤓','😈','👿','👹','👺','💀','👻','👽','🤖','💩','😺','😸','😹','😻','😼','😽','🙀','😿','😾','🤲','👐','🤝','👍','👎','👊','✊','🤛','🤜','🤞','✌️','🤟','🤘','👈','👉','👆','👇','☝️','✋','🤚','🖐','🖖','👋','🤙','💪','🖕','✍️','🙏','💍','💄','💋','👄','👅','👂','👃','👣','👁','👀','🧠','🗣','👤','👥'
|
||||
],
|
||||
embed: {
|
||||
post: (function(url, caption = true, likes = false, layout = 'full') {
|
||||
let u = url + '/embed?';
|
||||
u += caption ? 'caption=true&' : 'caption=false&';
|
||||
u += likes ? 'likes=true&' : 'likes=false&';
|
||||
u += layout == 'compact' ? 'layout=compact' : 'layout=full';
|
||||
return '<iframe src="'+u+'" class="pixelfed__embed" style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe><script async defer src="'+window.location.origin +'/embed.js"><\/script>';
|
||||
}),
|
||||
profile: (function(url) {
|
||||
// placeholder
|
||||
console.error('This method is not supported yet');
|
||||
})
|
||||
}
|
||||
|
||||
};
|
|
@ -98,6 +98,22 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<a class="d-none card mx-md-5 my-md-3 shadow-none border compose-action text-decoration-none text-dark" :click="showAddToStoryCard">
|
||||
<div class="card-body">
|
||||
<div class="media">
|
||||
<div class="mr-3 align-items-center justify-content-center" style="display:inline-flex;width:40px;height:40px;border-radius: 100%;background-color: #008DF5">
|
||||
<i class="fas fa-history text-white fa-lg"></i>
|
||||
</div>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0">
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">Add to Story</span>
|
||||
</p>
|
||||
<p class="mb-0 text-muted">Add a photo or video to your story.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a class="card mx-md-5 my-md-3 shadow-none border compose-action text-decoration-none text-dark" href="/i/collections/create">
|
||||
<div class="card-body">
|
||||
<div class="media">
|
||||
|
@ -132,9 +148,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<p>
|
||||
<a class="font-weight-bold" href="/site/help">Need Help?</a>
|
||||
<p class="pt-3">
|
||||
<a class="font-weight-bold" href="/site/help">Help</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -755,10 +770,6 @@ export default {
|
|||
this.pageTitle = '';
|
||||
|
||||
switch(this.page) {
|
||||
case 'addToStory':
|
||||
this.page = 1;
|
||||
break;
|
||||
|
||||
case 'cropPhoto':
|
||||
case 'editMedia':
|
||||
this.page = 2;
|
||||
|
@ -906,7 +917,8 @@ export default {
|
|||
.then(res => {
|
||||
this.cameraRollMedia = res.data;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
<img src="/img/pixelfed-icon-grey.svg">
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="d-block d-md-none px-0 border-top-0 mx-n3">
|
||||
<!-- <div class="d-block d-md-none px-0 border-top-0 mx-n3">
|
||||
<input class="form-control rounded-0" placeholder="Search" v-model="searchTerm" v-on:keyup.enter="searchSubmit">
|
||||
</div>
|
||||
<section class="d-none d-md-flex mb-md-2 pt-5 discover-bar" style="width:auto; overflow: auto hidden;" v-if="categories.length > 0">
|
||||
</div> -->
|
||||
<!-- <section class="d-none d-md-flex mb-md-2 pt-5 discover-bar" style="width:auto; overflow: auto hidden;" v-if="categories.length > 0">
|
||||
<a v-if="config.ab.loops == true" class="text-decoration-none bg-transparent border border-success rounded d-inline-flex align-items-center justify-content-center mr-3 card-disc" href="/discover/loops">
|
||||
<p class="text-success lead font-weight-bold mb-0">Loops</p>
|
||||
</a>
|
||||
|
@ -15,11 +15,39 @@
|
|||
<p class="text-white font-weight-bold" style="text-shadow: 3px 3px 16px #272634;">{{category.name}}</p>
|
||||
</a>
|
||||
|
||||
</section>
|
||||
</section> -->
|
||||
<section class="mb-5 section-explore">
|
||||
<div class="profile-timeline">
|
||||
<div class="row p-0">
|
||||
<div class="col-4 p-1 p-sm-2 p-md-3" v-for="post in posts">
|
||||
<div class="row p-0 mt-5">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="">
|
||||
<a class="card info-overlay card-md-border-0" :href="posts[0].url">
|
||||
<div class="square">
|
||||
<span v-if="posts[0].type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
<span v-if="posts[0].type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
|
||||
<span v-if="posts[0].type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
|
||||
<div class="square-content" v-bind:style="{ 'background-image': 'url(' + posts[0].thumb + ')' }">
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6 row p-0 m-0">
|
||||
<div v-for="(post, index) in posts.slice(1,5)" class="col-6" style="margin-bottom:1.8rem;">
|
||||
<a class="card info-overlay card-md-border-0" :href="post.url">
|
||||
<div class="square">
|
||||
<span v-if="post.type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
<span v-if="post.type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
|
||||
<span v-if="post.type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
|
||||
<div class="square-content" v-bind:style="{ 'background-image': 'url(' + post.thumb + ')' }">
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row p-0" style="display: flex;">
|
||||
<div v-for="(post, index) in posts.slice(5)" class="col-3 p-1 p-sm-2 p-md-3">
|
||||
<a class="card info-overlay card-md-border-0" :href="post.url">
|
||||
<div class="square">
|
||||
<span v-if="post.type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
</div>
|
||||
<form v-else class="border-0 rounded-0 align-middle" method="post" action="/i/comment" :data-id="statusId" data-truncate="false">
|
||||
<textarea class="form-control border-0 rounded-0" name="comment" placeholder="Add a comment…" autocomplete="off" autocorrect="off" style="height:56px;line-height: 18px;max-height:80px;resize: none; padding-right:4.2rem;" v-model="replyText"></textarea>
|
||||
<input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" v-on:click.prevent="postReply"/>
|
||||
<input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" v-on:click.prevent="postReply" :disabled="replyText.length == 0" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -351,7 +351,7 @@
|
|||
</span>
|
||||
<button
|
||||
:class="[replyText.length > 1 ? 'btn btn-sm font-weight-bold float-right btn-outline-dark ':'btn btn-sm font-weight-bold float-right btn-outline-lighter']"
|
||||
:disabled="replyText.length < 2"
|
||||
:disabled="replyText.length == 0 ? 'disabled':''"
|
||||
@click="postReply"
|
||||
>Post</button>
|
||||
</p>
|
||||
|
@ -547,6 +547,10 @@
|
|||
.momentui .carousel-item {
|
||||
background: #000 !important;
|
||||
}
|
||||
.reply-btn[disabled] {
|
||||
opacity: .3;
|
||||
color: #3897f0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
|
127
resources/assets/js/components/ProfileDirectory.vue
Normal file
127
resources/assets/js/components/ProfileDirectory.vue
Normal file
|
@ -0,0 +1,127 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="col-12">
|
||||
<p class="font-weight-bold text-lighter text-uppercase">Profiles Directory</p>
|
||||
<div v-if="loaded" class="">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-6 p-1" v-for="(profile, index) in profiles">
|
||||
<div class="card card-body border shadow-none py-2">
|
||||
<div class="media">
|
||||
<a :href="profile.url"><img :src="profile.avatar" class="rounded-circle border mr-3" alt="..." width="40px" height="40px"></a>
|
||||
<div class="media-body">
|
||||
<p class="mt-0 mb-0 font-weight-bold">
|
||||
<a :href="profile.url" class="text-dark">{{profile.username}}</a>
|
||||
</p>
|
||||
<p class="mb-1 small text-lighter d-flex justify-content-between font-weight-bold">
|
||||
<span>
|
||||
<span>{{prettyCount(profile.statuses_count)}}</span> POSTS
|
||||
</span>
|
||||
<span>
|
||||
<span>{{postsPerDay(profile)}}</span> POSTS/DAY
|
||||
</span>
|
||||
<span>
|
||||
<span>{{prettyCount(profile.followers_count)}}</span> FOLLOWERS
|
||||
</span>
|
||||
</p>
|
||||
<p class="mb-1">
|
||||
<span v-for="(post, i) in profile.posts" class="shadow-sm" :key="'profile_posts_'+i">
|
||||
<a :href="post.url" class="text-decoration-none mr-1">
|
||||
<img :src="thumbUrl(post)" width="62.3px" height="62.3px" class="border rounded">
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showLoadMore" class="col-12">
|
||||
<p class="text-center mb-0 pt-3">
|
||||
<button class="btn btn-outline-secondary btn-sm px-4 py-1 font-weight-bold" @click="loadMore()">Load More</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="row">
|
||||
<div class="col-12 d-flex justify-content-center align-items-center">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style type="text/css" scoped></style>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['profileId'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
showLoadMore: true,
|
||||
profiles: [],
|
||||
page: 1
|
||||
}
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
fetchData() {
|
||||
axios.get('/api/pixelfed/v2/discover/profiles', {
|
||||
params: {
|
||||
page: this.page
|
||||
}
|
||||
})
|
||||
.then(res => {
|
||||
if(res.data.length == 0) {
|
||||
this.showLoadMore = false;
|
||||
this.loaded = true;
|
||||
return;
|
||||
}
|
||||
this.profiles = res.data;
|
||||
this.showLoadMore = this.profiles.length == 8;
|
||||
this.loaded = true;
|
||||
});
|
||||
},
|
||||
|
||||
prettyCount(val) {
|
||||
return App.util.format.count(val);
|
||||
},
|
||||
|
||||
loadMore() {
|
||||
this.loaded = false;
|
||||
this.page++;
|
||||
this.fetchData();
|
||||
},
|
||||
|
||||
thumbUrl(p) {
|
||||
return p.media_attachments[0].url;
|
||||
},
|
||||
|
||||
postsPerDay(profile) {
|
||||
let created = profile.created_at;
|
||||
let now = Date.now();
|
||||
let diff = Math.abs(created, now)
|
||||
let day = 1000 * 60 * 60 * 24;
|
||||
let days = Math.round(diff / day);
|
||||
|
||||
let statuses = profile.statuses_count;
|
||||
|
||||
let perDay = this.prettyCount(Math.floor(statuses / days));
|
||||
console.log(perDay);
|
||||
return perDay;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -11,31 +11,31 @@
|
|||
|
||||
<div v-if="!loading && !networkError" class="mt-5 row">
|
||||
|
||||
<div class="col-12 col-md-3 mb-4">
|
||||
<div class="col-12 col-md-2 mb-4">
|
||||
<div v-if="results.hashtags || results.profiles || results.statuses">
|
||||
<p class="font-weight-bold">Filters</p>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="filter1" v-model="filters.hashtags">
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter1">Show Hashtags</label>
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter1">Hashtags</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="filter2" v-model="filters.profiles">
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter2">Show Profiles</label>
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter2">Profiles</label>
|
||||
</div>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="filter3" v-model="filters.statuses">
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter3">Show Statuses</label>
|
||||
<label class="custom-control-label text-muted font-weight-light" for="filter3">Statuses</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-9">
|
||||
<div class="col-12 col-md-10">
|
||||
<p class="h5 font-weight-bold">Showing results for <i>{{query}}</i></p>
|
||||
<hr>
|
||||
|
||||
<div v-if="filters.hashtags && results.hashtags" class="row mb-4">
|
||||
<p class="col-12 font-weight-bold text-muted">Hashtags</p>
|
||||
<a v-for="(hashtag, index) in results.hashtags" class="col-12 col-md-3 mb-3" style="text-decoration: none;" :href="hashtag.url">
|
||||
<div class="card card-body text-center">
|
||||
<div class="card card-body text-center shadow-none border">
|
||||
<p class="lead mb-0 text-truncate text-dark" data-toggle="tooltip" :title="hashtag.value">
|
||||
#{{hashtag.value}}
|
||||
</p>
|
||||
|
@ -49,7 +49,7 @@
|
|||
<div v-if="filters.profiles && results.profiles" class="row mb-4">
|
||||
<p class="col-12 font-weight-bold text-muted">Profiles</p>
|
||||
<a v-for="(profile, index) in results.profiles" class="col-12 col-md-4 mb-3" style="text-decoration: none;" :href="profile.url">
|
||||
<div class="card card-body text-center">
|
||||
<div class="card card-body text-center shadow-none border">
|
||||
<p class="text-center">
|
||||
<img :src="profile.entity.thumb" width="32px" height="32px" class="rounded-circle box-shadow">
|
||||
</p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="container" style="">
|
||||
<div class="row">
|
||||
<div v-if="layout === 'feed'" class="row">
|
||||
<div :class="[modes.distractionFree ? 'col-md-8 col-lg-8 offset-md-2 px-0 my-sm-3 timeline order-2 order-md-1':'col-md-8 col-lg-8 px-0 my-sm-3 timeline order-2 order-md-1']">
|
||||
<div class="d-none" data-id="StoryTimelineComponent"></div>
|
||||
<div style="padding-top:10px;">
|
||||
|
@ -211,13 +211,13 @@
|
|||
<div v-if="status.id == replyId && !status.comments_disabled" class="card-footer bg-white sticky-md-bottom p-0">
|
||||
<form class="border-0 rounded-0 align-middle" method="post" action="/i/comment" :data-id="status.id" data-truncate="false">
|
||||
<textarea class="form-control border-0 rounded-0" name="comment" placeholder="Add a comment…" autocomplete="off" autocorrect="off" style="height:56px;line-height: 18px;max-height:80px;resize: none; padding-right:4.2rem;" v-model="replyText"></textarea>
|
||||
<input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" v-on:click.prevent="commentSubmit(status, $event)"/>
|
||||
<input type="button" value="Post" class="d-inline-block btn btn-link font-weight-bold reply-btn text-decoration-none" v-on:click.prevent="commentSubmit(status, $event)" :disabled="replyText.length == 0" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && feed.length">
|
||||
<div class="card shadow-none border">
|
||||
<div class="card shadow-none">
|
||||
<div class="card-body">
|
||||
<infinite-loading @infinite="infiniteTimeline" :distance="800">
|
||||
<div slot="no-more" class="font-weight-bold">No more posts to load</div>
|
||||
|
@ -227,7 +227,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && scope == 'home' && feed.length == 0">
|
||||
<div class="card">
|
||||
<div class="card shadow-none border">
|
||||
<div class="card-body text-center">
|
||||
<p class="h2 font-weight-lighter p-5">Hello, {{profile.acct}}</p>
|
||||
<p class="text-lighter"><i class="fas fa-camera-retro fa-5x"></i></p>
|
||||
|
@ -240,7 +240,7 @@
|
|||
</div>
|
||||
|
||||
<div v-if="!modes.distractionFree" class="col-md-4 col-lg-4 my-3 order-1 order-md-2 d-none d-md-block">
|
||||
<div class="position-sticky" style="top:68px;">
|
||||
<div class="position-sticky" style="top:78px;">
|
||||
<div class="mb-4">
|
||||
<div class="">
|
||||
<div class="">
|
||||
|
@ -327,11 +327,11 @@
|
|||
<p class="mb-0 text-uppercase font-weight-bold text-muted small">
|
||||
<a href="/site/about" class="text-dark pr-2">About Us</a>
|
||||
<a href="/site/help" class="text-dark pr-2">Help</a>
|
||||
<a href="/site/open-source" class="text-dark pr-2">Open Source</a>
|
||||
<a href="/site/language" class="text-dark pr-2">Language</a>
|
||||
<a href="/site/terms" class="text-dark pr-2">Terms</a>
|
||||
<a href="/site/privacy" class="text-dark pr-2">Privacy</a>
|
||||
<a href="/discover/profiles" class="text-dark pr-2">Profiles</a>
|
||||
<a href="/discover/places" class="text-dark pr-2">Places</a>
|
||||
<a href="/site/privacy" class="text-dark pr-2">Privacy</a>
|
||||
<a href="/site/terms" class="text-dark pr-2">Terms</a>
|
||||
</p>
|
||||
<p class="mb-0 text-uppercase font-weight-bold text-muted small">
|
||||
<a href="http://pixelfed.org" class="text-muted" rel="noopener" title="" data-toggle="tooltip">Powered by Pixelfed</a>
|
||||
|
@ -341,40 +341,91 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<b-modal ref="ctxModal"
|
||||
id="ctx-modal"
|
||||
hide-header
|
||||
hide-footer
|
||||
centered
|
||||
rounded
|
||||
size="sm"
|
||||
body-class="list-group-flush p-0 rounded">
|
||||
<div class="list-group text-center">
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuReportPost()">Report inappropriate</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuUnfollow()">Unfollow</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && !ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-primary" @click="ctxMenuFollow()">Follow</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">Go to post</div>
|
||||
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxMenuEmbed()">Embed</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuShare()">Share</div> -->
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div>
|
||||
<div v-if="profile && profile.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenuShow()">Moderation Tools</div>
|
||||
<div v-if="ctxMenuStatus && (profile.is_admin || profile.id == ctxMenuStatus.account.id)" class="list-group-item rounded cursor-pointer" @click="deletePost(ctxMenuStatus)">Delete</div>
|
||||
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxMenu()">Cancel</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
<b-modal ref="ctxModModal"
|
||||
id="ctx-mod-modal"
|
||||
hide-header
|
||||
hide-footer
|
||||
centered
|
||||
rounded
|
||||
size="sm"
|
||||
body-class="list-group-flush p-0 rounded">
|
||||
<div class="list-group text-center">
|
||||
<div class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'unlist')">Unlist from Timelines</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="">Add Content Warning</div>
|
||||
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModMenuClose()">Cancel</div>
|
||||
</div>
|
||||
<div v-else class="row pt-2">
|
||||
<div class="col-12">
|
||||
<div v-if="loading" class="text-center">
|
||||
<div class="spinner-border" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="row">
|
||||
<div class="col-12 col-md-4 p-1 p-md-3 mb-3" v-for="(s, index) in feed" :key="`${index}-${s.id}`">
|
||||
<div class="card info-overlay card-md-border-0 shadow-sm border border-light" :href="statusUrl(s)">
|
||||
<div :class="[s.sensitive ? 'square' : 'square ' + s.media_attachments[0].filter_class]">
|
||||
<span v-if="s.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
|
||||
<span v-if="s.pf_type == 'video:album'" class="float-right mr-3 post-icon"><i class="fas fa-film fa-2x"></i></span>
|
||||
<div class="square-content" v-bind:style="previewBackground(s)">
|
||||
</div>
|
||||
<div class="info-overlay-text px-4">
|
||||
<p class="text-white m-auto text-center">
|
||||
{{trimCaption(s.content_text)}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="py-3 media align-items-center">
|
||||
<img :src="s.account.avatar" class="mr-3 rounded-circle shadow-sm" :alt="s.account.username + ' \'s avatar'" width="30px" height="30px">
|
||||
<div class="media-body">
|
||||
<p class="mb-0 font-weight-bold small">{{s.account.username}}</p>
|
||||
<p class="mb-0" style="line-height: 0.7;">
|
||||
<a :href="statusUrl(s)" class="small text-lighter">
|
||||
<timeago :datetime="s.created_at" :auto-update="60" :converter-options="{includeSeconds:true}" :title="timestampFormat(s.created_at)" v-b-tooltip.hover.bottom></timeago>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<p class="mb-0">
|
||||
<span class="font-weight-bold small">{{s.favourites_count == 1 ? '1 like' : s.favourites_count+' likes'}}</span>
|
||||
<span class="px-2"><i v-bind:class="[s.favourited ? 'fas fa-heart text-danger cursor-pointer' : 'far fa-heart like-btn text-lighter cursor-pointer']" v-on:click="likeStatus(s, $event)"></i></span>
|
||||
<span class="mr-2 cursor-pointer"><i class="fas fa-ellipsis-v" @click="ctxMenu(s)"></i></span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!loading && feed.length">
|
||||
<infinite-loading @infinite="infiniteTimeline" :distance="800">
|
||||
<div slot="no-more" class="font-weight-bold">No more posts to load</div>
|
||||
<div slot="no-results" class="font-weight-bold">No more posts to load</div>
|
||||
</infinite-loading>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<b-modal ref="ctxModal"
|
||||
id="ctx-modal"
|
||||
hide-header
|
||||
hide-footer
|
||||
centered
|
||||
rounded
|
||||
size="sm"
|
||||
body-class="list-group-flush p-0 rounded">
|
||||
<div class="list-group text-center">
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuReportPost()">Report inappropriate</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-danger" @click="ctxMenuUnfollow()">Unfollow</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.account.id != profile.id && ctxMenuRelationship && !ctxMenuRelationship.following" class="list-group-item rounded cursor-pointer font-weight-bold text-primary" @click="ctxMenuFollow()">Follow</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuGoToPost()">Go to post</div>
|
||||
<div v-if="ctxMenuStatus && ctxMenuStatus.local == true" class="list-group-item rounded cursor-pointer" @click="ctxMenuEmbed()">Embed</div>
|
||||
<!-- <div class="list-group-item rounded cursor-pointer" @click="ctxMenuShare()">Share</div> -->
|
||||
<div class="list-group-item rounded cursor-pointer" @click="ctxMenuCopyLink()">Copy Link</div>
|
||||
<div v-if="profile && profile.is_admin == true" class="list-group-item rounded cursor-pointer" @click="ctxModMenuShow()">Moderation Tools</div>
|
||||
<div v-if="ctxMenuStatus && (profile.is_admin || profile.id == ctxMenuStatus.account.id)" class="list-group-item rounded cursor-pointer" @click="deletePost(ctxMenuStatus)">Delete</div>
|
||||
<div class="list-group-item rounded cursor-pointer text-lighter" @click="closeCtxMenu()">Cancel</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
<b-modal ref="ctxModModal"
|
||||
id="ctx-mod-modal"
|
||||
hide-header
|
||||
hide-footer
|
||||
centered
|
||||
rounded
|
||||
size="sm"
|
||||
body-class="list-group-flush p-0 rounded">
|
||||
<div class="list-group text-center">
|
||||
<div class="list-group-item rounded cursor-pointer" @click="moderatePost(ctxMenuStatus, 'unlist')">Unlist from Timelines</div>
|
||||
<div class="list-group-item rounded cursor-pointer" @click="">Add Content Warning</div>
|
||||
<div class="list-group-item rounded cursor-pointer text-lighter" @click="ctxModMenuClose()">Cancel</div>
|
||||
</div>
|
||||
</b-modal>
|
||||
<b-modal ref="ctxShareModal"
|
||||
id="ctx-share-modal"
|
||||
|
@ -402,10 +453,10 @@
|
|||
size="md"
|
||||
body-class="p-2 rounded">
|
||||
<div>
|
||||
<textarea class="form-control disabled" rows="1" style="border: 1px solid #efefef; font-size: 14px; line-height: 17px; min-height: 37px; margin: 0 0 7px; resize: none; white-space: nowrap;" v-model="ctxEmbedPayload"></textarea>
|
||||
<textarea class="form-control disabled" rows="1" style="border: 1px solid #efefef; font-size: 14px; line-height: 12px; height: 37px; margin: 0 0 7px; resize: none; white-space: nowrap;" v-model="ctxEmbedPayload"></textarea>
|
||||
<hr>
|
||||
<button :class="copiedEmbed ? 'btn btn-primary btn-block btn-sm py-1 font-weight-bold disabed': 'btn btn-primary btn-block btn-sm py-1 font-weight-bold'" @click="ctxCopyEmbed" :disabled="copiedEmbed">{{copiedEmbed ? 'Embed Code Copied!' : 'Copy Embed Code'}}</button>
|
||||
<p class="mb-0 px-2 small text-muted">By using this embed, you agree to our <a href="#">API Terms of Use</a>.</p>
|
||||
<p class="mb-0 px-2 small text-muted">By using this embed, you agree to our <a href="/site/terms">Terms of Use</a></p>
|
||||
</div>
|
||||
</b-modal>
|
||||
<b-modal
|
||||
|
@ -454,11 +505,15 @@
|
|||
height: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
.reply-btn[disabled] {
|
||||
opacity: .3;
|
||||
color: #3897f0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
export default {
|
||||
props: ['scope'],
|
||||
props: ['scope', 'layout'],
|
||||
data() {
|
||||
return {
|
||||
ids: [],
|
||||
|
@ -1177,10 +1232,7 @@
|
|||
|
||||
ctxMenu(status) {
|
||||
this.ctxMenuStatus = status;
|
||||
// let payload = '<div class="pixlfed-media" data-id="'+ this.ctxMenuStatus.id + '"></div><script ';
|
||||
// payload += 'src="https://pixelfed.dev/js/embed.js" async><';
|
||||
// payload += '/script>';
|
||||
// this.ctxEmbedPayload = payload;
|
||||
this.ctxEmbedPayload = window.App.util.embed.post(status.url);
|
||||
if(status.account.id == this.profile.id) {
|
||||
this.$refs.ctxModal.show();
|
||||
} else {
|
||||
|
@ -1354,6 +1406,21 @@
|
|||
break;
|
||||
}
|
||||
},
|
||||
|
||||
previewUrl(status) {
|
||||
return status.sensitive ? '/storage/no-preview.png?v=' + new Date().getTime() : status.media_attachments[0].preview_url;
|
||||
},
|
||||
|
||||
previewBackground(status) {
|
||||
let preview = this.previewUrl(status);
|
||||
return 'background-image: url(' + preview + ');';
|
||||
},
|
||||
|
||||
trimCaption(caption, len = 60) {
|
||||
return _.truncate(caption, {
|
||||
length: len
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
4
resources/assets/js/profile-directory.js
vendored
Normal file
4
resources/assets/js/profile-directory.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
Vue.component(
|
||||
'profile-directory',
|
||||
require('./components/ProfileDirectory.vue').default
|
||||
);
|
4
resources/assets/sass/custom.scss
vendored
4
resources/assets/sass/custom.scss
vendored
|
@ -37,10 +37,6 @@ body, button, input, textarea {
|
|||
color: #212529 !important;
|
||||
}
|
||||
|
||||
.settings-nav .active {
|
||||
border-left: 2px solid #6c757d !important
|
||||
}
|
||||
|
||||
.settings-nav .active .nav-link{
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
17
resources/views/discover/profiles/home.blade.php
Normal file
17
resources/views/discover/profiles/home.blade.php
Normal file
|
@ -0,0 +1,17 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="col-12">
|
||||
<profile-directory profile-id="{{Auth::user()->profile_id}}"></profile-directory>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{mix('js/compose.js')}}"></script>
|
||||
<script type="text/javascript" src="{{mix('js/profile-directory.js')}}"></script>
|
||||
<script type="text/javascript">App.boot();</script>
|
||||
@endpush
|
|
@ -75,7 +75,7 @@
|
|||
</div>
|
||||
<div class="col-12 col-md-5 offset-md-1">
|
||||
<div>
|
||||
<div class="card my-4">
|
||||
<div class="card my-4 shadow-none border">
|
||||
<div class="card-body px-lg-5">
|
||||
<div class="text-center pt-3">
|
||||
<img src="/img/pixelfed-icon-color.svg">
|
||||
|
@ -86,7 +86,7 @@
|
|||
</div>
|
||||
<div>
|
||||
@if(true === config('pixelfed.open_registration'))
|
||||
<form class="px-1" method="POST" action="{{ route('register') }}">
|
||||
<form class="px-1" method="POST" action="{{ route('register') }}" id="register_form">
|
||||
@csrf
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
|
@ -102,7 +102,7 @@
|
|||
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<input id="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" placeholder="{{ __('Username') }}" required>
|
||||
<input id="username" type="text" class="form-control{{ $errors->has('username') ? ' is-invalid' : '' }}" name="username" value="{{ old('username') }}" placeholder="{{ __('Username') }}" required maxlength="15" minlength="2">
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<span class="invalid-feedback">
|
||||
|
@ -141,6 +141,16 @@
|
|||
<input id="password-confirm" type="password" class="form-control" name="password_confirmation" placeholder="{{ __('Confirm Password') }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" name="agecheck" type="checkbox" value="true" id="ageCheck" required>
|
||||
<label class="form-check-label" for="ageCheck">
|
||||
I am at least 16 years old
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<button type="submit" class="btn btn-primary btn-block py-0 font-weight-bold">
|
||||
|
@ -161,7 +171,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-body">
|
||||
<div class="card shadow-none border card-body">
|
||||
<p class="text-center mb-0 font-weight-bold">Have an account? <a href="/login">Log in</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
46
resources/views/status/embed-removed.blade.php
Normal file
46
resources/views/status/embed-removed.blade.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<title>Pixelfed | 404 Embed Not Found</title>
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta name="medium" content="image">
|
||||
<meta name="theme-color" content="#10c5f8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="shortcut icon" type="image/png" href="/img/favicon.png?v=2">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/img/favicon.png?v=2">
|
||||
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body.embed-card {
|
||||
background: #fff !important;
|
||||
margin: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.status-card-embed {
|
||||
box-shadow: none;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-white">
|
||||
<div class="embed-card">
|
||||
<div class="card status-card-embed card-md-rounded-0 border card-body border shadow-none rounded-0 d-flex justify-content-center align-items-center">
|
||||
<div class="text-center p-5">
|
||||
<img src="/img/pixelfed-icon-color.svg" width="40px" height="40px">
|
||||
<p class="h2 py-3 font-weight-bold">Pixelfed</p>
|
||||
<p style="font-size:14px;font-weight: 500;" class="p-2">The link to this photo or video may be broken, or the post may have been removed.</p>
|
||||
<p><a href="{{config('app.url')}}" class="font-weight-bold" target="_blank">Visit Pixelfed</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">window.addEventListener("message",e=>{const t=e.data||{};window.parent&&"setHeight"===t.type&&window.parent.postMessage({type:"setHeight",id:t.id,height:document.getElementsByTagName("html")[0].scrollHeight},"*")});</script>
|
||||
</body>
|
||||
</html>
|
178
resources/views/status/embed.blade.php
Normal file
178
resources/views/status/embed.blade.php
Normal file
|
@ -0,0 +1,178 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ app()->getLocale() }}">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
|
||||
<title>{{ $title ?? config('app.name', 'Pixelfed') }}</title>
|
||||
|
||||
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="{{$status->url()}}">
|
||||
<meta name="medium" content="image">
|
||||
<meta name="theme-color" content="#10c5f8">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="shortcut icon" type="image/png" href="/img/favicon.png?v=2">
|
||||
<link rel="apple-touch-icon" type="image/png" href="/img/favicon.png?v=2">
|
||||
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
|
||||
<style type="text/css">
|
||||
body.embed-card {
|
||||
background: #fff !important;
|
||||
margin: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.status-card-embed {
|
||||
box-shadow: none;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-white">
|
||||
<div class="embed-card">
|
||||
@php($item = $status)
|
||||
<div class="card status-card-embed card-md-rounded-0 border">
|
||||
<div class="card-header d-inline-flex align-items-center bg-white">
|
||||
<img src="{{$item->profile->avatarUrl()}}" width="32px" height="32px" target="_blank" style="border-radius: 32px;">
|
||||
<a class="username font-weight-bold pl-2 text-dark" target="_blank" href="{{$item->profile->url()}}">
|
||||
{{$item->profile->username}}
|
||||
</a>
|
||||
</div>
|
||||
<a href="{{$status->url()}}" target="_blank">
|
||||
@php($status = $item)
|
||||
@switch($status->viewType())
|
||||
@case('photo')
|
||||
@case('image')
|
||||
@if($status->is_nsfw)
|
||||
<details class="details-animated">
|
||||
<summary>
|
||||
<p class="mb-0 lead font-weight-bold">CW / NSFW / Hidden Media</p>
|
||||
<p class="font-weight-light">(click to show)</p>
|
||||
</summary>
|
||||
<a class="max-hide-overflow {{$status->firstMedia()->filter_class}}" href="{{$status->url()}}" target="_blank">
|
||||
<img class="card-img-top" src="{{$status->mediaUrl()}}">
|
||||
</a>
|
||||
</details>
|
||||
@else
|
||||
<div class="{{$status->firstMedia()->filter_class}}">
|
||||
<img src="{{$status->mediaUrl()}}" width="100%">
|
||||
</div>
|
||||
@endif
|
||||
@break
|
||||
@case('album')
|
||||
@if($status->is_nsfw)
|
||||
|
||||
@else
|
||||
<div id="photo-carousel-wrapper-{{$status->id}}" class="carousel slide carousel-fade" data-ride="carousel">
|
||||
<ol class="carousel-indicators">
|
||||
@for($i = 0; $i < $status->media_count; $i++)
|
||||
<li data-target="#photo-carousel-wrapper-{{$status->id}}" data-slide-to="{{$i}}" class="{{$i == 0 ? 'active' : ''}}"></li>
|
||||
@endfor
|
||||
</ol>
|
||||
<div class="carousel-inner">
|
||||
@foreach($status->media()->orderBy('order')->get() as $media)
|
||||
<div class="carousel-item {{$loop->iteration == 1 ? 'active' : ''}}">
|
||||
<figure class="{{$media->filter_class}}">
|
||||
<span class="float-right mr-3 badge badge-dark" style="position:fixed;top:8px;right:0;margin-bottom:-20px;">{{$loop->iteration}}/{{$loop->count}}</span>
|
||||
<img class="d-block w-100" src="{{$media->url()}}" alt="{{$status->caption}}">
|
||||
</figure>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<a class="carousel-control-prev" href="#photo-carousel-wrapper-{{$status->id}}" role="button" data-slide="prev">
|
||||
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="carousel-control-next" href="#photo-carousel-wrapper-{{$status->id}}" role="button" data-slide="next">
|
||||
<span class="carousel-control-next-icon" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
@break
|
||||
@case('video')
|
||||
@if($status->is_nsfw)
|
||||
<details class="details-animated">
|
||||
<summary>
|
||||
<p class="mb-0 lead font-weight-bold">CW / NSFW / Hidden Media</p>
|
||||
<p class="font-weight-light">(click to show)</p>
|
||||
</summary>
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<video class="video" preload="none" controls loop>
|
||||
<source src="{{$status->firstMedia()->url()}}" type="{{$status->firstMedia()->mime}}">
|
||||
</video>
|
||||
</div>
|
||||
</details>
|
||||
@else
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<video class="video" preload="none" controls loop>
|
||||
<source src="{{$status->firstMedia()->url()}}" type="{{$status->firstMedia()->mime}}">
|
||||
</video>
|
||||
</div>
|
||||
@endif
|
||||
@break
|
||||
@case('video-album')
|
||||
@if($status->is_nsfw)
|
||||
<details class="details-animated">
|
||||
<summary>
|
||||
<p class="mb-0 lead font-weight-bold">CW / NSFW / Hidden Media</p>
|
||||
<p class="font-weight-light">(click to show)</p>
|
||||
</summary>
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<video class="video" preload="none" controls loop>
|
||||
<source src="{{$status->firstMedia()->url()}}" type="{{$status->firstMedia()->mime}}">
|
||||
</video>
|
||||
</div>
|
||||
</details>
|
||||
@else
|
||||
<div class="embed-responsive embed-responsive-16by9">
|
||||
<video class="video" preload="none" controls loop>
|
||||
<source src="{{$status->firstMedia()->url()}}" type="{{$status->firstMedia()->mime}}">
|
||||
</video>
|
||||
</div>
|
||||
@endif
|
||||
@break
|
||||
@endswitch
|
||||
</a>
|
||||
@if($layout != 'compact')
|
||||
<div class="card-body">
|
||||
<div class="view-more mb-2">
|
||||
<a class="font-weight-bold" href="{{$status->url()}}" target="_blank">View More on Pixelfed</a>
|
||||
</div>
|
||||
<hr>
|
||||
@if($showLikes)
|
||||
<div class="likes font-weight-bold pb-2">
|
||||
<span class="like-count">{{$item->likes_count}}</span> likes
|
||||
</div>
|
||||
@endif
|
||||
<div class="caption">
|
||||
<p class="my-0">
|
||||
<span class="username font-weight-bold">
|
||||
<bdi><a class="text-dark" href="{{$item->profile->url()}}" target="_blank">{{$item->profile->username}}</a></bdi>
|
||||
</span>
|
||||
@if($showCaption)
|
||||
<span class="caption-container">{!! $item->rendered ?? e($item->caption) !!}</span>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="card-footer bg-white d-inline-flex justify-content-between align-items-center">
|
||||
<div class="timestamp">
|
||||
<p class="small text-uppercase mb-0"><a href="{{$item->url()}}" class="text-muted" target="_blank">{{$item->created_at->diffForHumans()}}</a></p>
|
||||
</div>
|
||||
<div>
|
||||
<a class="small font-weight-bold text-muted pr-1" href="{{config('app.url')}}" target="_blank">{{config('pixelfed.domain.app')}}</a>
|
||||
<a href="https://pixelfed.org" target="_blank"><img src="/img/pixelfed-icon-color.svg" width="26px"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">window.addEventListener("message",e=>{const t=e.data||{};window.parent&&"setHeight"===t.type&&window.parent.postMessage({type:"setHeight",id:t.id,height:document.getElementsByTagName("html")[0].scrollHeight},"*")});</script>
|
||||
<script type="text/javascript">document.querySelectorAll('.caption-container a').forEach(function(i) {i.setAttribute('target', '_blank');});</script>
|
||||
</body>
|
||||
</html>
|
|
@ -2,10 +2,24 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<timeline scope="home"></timeline>
|
||||
<timeline scope="home" layout="feed"></timeline>
|
||||
|
||||
@endsection
|
||||
|
||||
|
||||
@if($layout == 'grid')
|
||||
@push('styles')
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: #fff !important;
|
||||
}
|
||||
.navbar.border-bottom {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
@endif
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{ mix('js/timeline.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ mix('js/compose.js') }}"></script>
|
||||
|
|
|
@ -2,10 +2,23 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<timeline scope="local"></timeline>
|
||||
<timeline scope="local" layout="feed"></timeline>
|
||||
|
||||
@endsection
|
||||
|
||||
@if($layout == 'grid')
|
||||
@push('styles')
|
||||
<style type="text/css">
|
||||
body {
|
||||
background: #fff !important;
|
||||
}
|
||||
.navbar.border-bottom {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
@endif
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript" src="{{ mix('js/timeline.js') }}"></script>
|
||||
<script type="text/javascript" src="{{ mix('js/compose.js') }}"></script>
|
||||
|
|
|
@ -71,6 +71,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::redirect('discover/personal', '/discover');
|
||||
Route::get('discover', 'DiscoverController@home')->name('discover');
|
||||
Route::get('discover/loops', 'DiscoverController@showLoops');
|
||||
Route::get('discover/profiles', 'DiscoverController@profilesDirectory')->name('discover.profiles');
|
||||
|
||||
|
||||
Route::group(['prefix' => 'api'], function () {
|
||||
Route::get('search', 'SearchController@searchAPI');
|
||||
|
@ -117,6 +119,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::get('config', 'ApiController@siteConfiguration');
|
||||
Route::get('discover', 'InternalApiController@discover');
|
||||
Route::get('discover/posts', 'InternalApiController@discoverPosts');
|
||||
Route::get('discover/profiles', 'DiscoverController@profilesDirectoryApi');
|
||||
Route::get('profile/{username}/status/{postid}', 'PublicApiController@status');
|
||||
Route::get('comments/{username}/status/{postId}', 'PublicApiController@statusComments');
|
||||
Route::get('likes/profile/{username}/status/{id}', 'PublicApiController@statusLikes');
|
||||
|
@ -373,6 +376,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
|
||||
Route::get('c/{collection}', 'CollectionController@show');
|
||||
Route::get('p/{username}/{id}/c', 'CommentController@showAll');
|
||||
Route::get('p/{username}/{id}/embed', 'StatusController@showEmbed');
|
||||
Route::get('p/{username}/{id}/edit', 'StatusController@edit');
|
||||
Route::post('p/{username}/{id}/edit', 'StatusController@editStore');
|
||||
Route::get('p/{username}/{id}.json', 'StatusController@showObject');
|
||||
|
|
8
webpack.mix.js
vendored
8
webpack.mix.js
vendored
|
@ -29,12 +29,14 @@ mix.js('resources/assets/js/app.js', 'public/js')
|
|||
.js('resources/assets/js/lib/ace/ace.js', 'public/js')
|
||||
.js('resources/assets/js/lib/ace/mode-dot.js', 'public/js')
|
||||
.js('resources/assets/js/lib/ace/theme-monokai.js', 'public/js')
|
||||
// .js('resources/assets/js/embed.js', 'public')
|
||||
// .js('resources/assets/js/direct.js', 'public/js')
|
||||
.js('resources/assets/js/hashtag.js', 'public/js')
|
||||
.js('resources/assets/js/collectioncompose.js', 'public/js')
|
||||
.js('resources/assets/js/collections.js', 'public/js')
|
||||
//.js('resources/assets/js/admin.js', 'public/js')
|
||||
.js('resources/assets/js/profile-directory.js', 'public/js')
|
||||
// .js('resources/assets/js/embed.js', 'public')
|
||||
// .js('resources/assets/js/direct.js', 'public/js')
|
||||
// .js('resources/assets/js/admin.js', 'public/js')
|
||||
// .js('resources/assets/js/micro.js', 'public/js')
|
||||
|
||||
.extract([
|
||||
'lodash',
|
||||
|
|
Loading…
Add table
Reference in a new issue