mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-10 16:44:50 +00:00
commit
1b7ef61a4a
31 changed files with 871 additions and 421 deletions
|
@ -67,6 +67,11 @@
|
|||
- Updated AdminInstanceController, invalidate banned domain cache when updated. ([35393edf](https://github.com/pixelfed/pixelfed/commit/35393edf))
|
||||
- Updated AP Helpers, use instance filtering. ([66b4f8c7](https://github.com/pixelfed/pixelfed/commit/66b4f8c7))
|
||||
- Updated ApiV1Controller, add missing instance api attributes. ([64b86546](https://github.com/pixelfed/pixelfed/commit/64b86546))
|
||||
- Updated story garbage collection, handle non active stories and new ephemeral story media directory. ([c43f8bcc](https://github.com/pixelfed/pixelfed/commit/c43f8bcc))
|
||||
- Updated Stories, add crop and duration settings to composer. ([c8edca69](https://github.com/pixelfed/pixelfed/commit/c8edca69))
|
||||
- Updated instance endpoint, add custom description. ([668e936e](https://github.com/pixelfed/pixelfed/commit/668e936e))
|
||||
- Updated StoryCompose component, improve full screen preview. ([39a76103](https://github.com/pixelfed/pixelfed/commit/39a76103))
|
||||
- Updated Helpers, fix broken tests. ([22dddaa0](https://github.com/pixelfed/pixelfed/commit/22dddaa0))
|
||||
- ([](https://github.com/pixelfed/pixelfed/commit/))
|
||||
|
||||
## [v0.10.10 (2021-01-28)](https://github.com/pixelfed/pixelfed/compare/v0.10.9...v0.10.10)
|
||||
|
|
|
@ -3,103 +3,127 @@
|
|||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\{
|
||||
DB,
|
||||
Storage
|
||||
};
|
||||
use App\{
|
||||
Story,
|
||||
StoryView
|
||||
};
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Story;
|
||||
use App\StoryView;
|
||||
|
||||
class StoryGC extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'story:gc';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'story:gc';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clear expired Stories';
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Clear expired Stories';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->directoryScan();
|
||||
$this->deleteViews();
|
||||
$this->deleteStories();
|
||||
}
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->directoryScan();
|
||||
$this->deleteViews();
|
||||
$this->deleteStories();
|
||||
}
|
||||
|
||||
protected function directoryScan()
|
||||
{
|
||||
$day = now()->day;
|
||||
protected function directoryScan()
|
||||
{
|
||||
$hour = now()->hour;
|
||||
|
||||
if($day != 3) {
|
||||
return;
|
||||
}
|
||||
if($hour !== 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
$monthHash = substr(hash('sha1', date('Y').date('m')), 0, 12);
|
||||
$monthHash = substr(hash('sha1', date('Y').date('m')), 0, 12);
|
||||
|
||||
$t1 = Storage::directories('public/_esm.t1');
|
||||
$t2 = Storage::directories('public/_esm.t2');
|
||||
$t1 = Storage::directories('public/_esm.t1');
|
||||
$t2 = Storage::directories('public/_esm.t2');
|
||||
|
||||
$dirs = array_merge($t1, $t2);
|
||||
$dirs = array_merge($t1, $t2);
|
||||
|
||||
foreach($dirs as $dir) {
|
||||
$hash = last(explode('/', $dir));
|
||||
if($hash != $monthHash) {
|
||||
$this->info('Found directory to delete: ' . $dir);
|
||||
$this->deleteDirectory($dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($dirs as $dir) {
|
||||
$hash = last(explode('/', $dir));
|
||||
if($hash != $monthHash) {
|
||||
$this->info('Found directory to delete: ' . $dir);
|
||||
$this->deleteDirectory($dir);
|
||||
}
|
||||
}
|
||||
|
||||
protected function deleteDirectory($path)
|
||||
{
|
||||
Storage::deleteDirectory($path);
|
||||
}
|
||||
$mh = hash('sha256', date('Y').'-.-'.date('m'));
|
||||
$monthHash = date('Y').date('m').substr($mh, 0, 6).substr($mh, 58, 6);
|
||||
$dirs = Storage::directories('public/_esm.t3');
|
||||
|
||||
protected function deleteViews()
|
||||
{
|
||||
StoryView::where('created_at', '<', now()->subMinutes(1441))->delete();
|
||||
}
|
||||
foreach($dirs as $dir) {
|
||||
$hash = last(explode('/', $dir));
|
||||
if($hash != $monthHash) {
|
||||
$this->info('Found directory to delete: ' . $dir);
|
||||
$this->deleteDirectory($dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function deleteStories()
|
||||
{
|
||||
$stories = Story::where('created_at', '<', now()->subMinutes(1441))->take(50)->get();
|
||||
protected function deleteDirectory($path)
|
||||
{
|
||||
Storage::deleteDirectory($path);
|
||||
}
|
||||
|
||||
if($stories->count() == 0) {
|
||||
exit;
|
||||
}
|
||||
protected function deleteViews()
|
||||
{
|
||||
StoryView::where('created_at', '<', now()->subMinutes(1441))->delete();
|
||||
}
|
||||
|
||||
foreach($stories as $story) {
|
||||
if(Storage::exists($story->path) == true) {
|
||||
Storage::delete($story->path);
|
||||
}
|
||||
DB::transaction(function() use($story) {
|
||||
StoryView::whereStoryId($story->id)->delete();
|
||||
$story->delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
protected function deleteStories()
|
||||
{
|
||||
$stories = Story::where('created_at', '>', now()->subMinutes(30))
|
||||
->whereNull('active')
|
||||
->get();
|
||||
|
||||
foreach($stories as $story) {
|
||||
if(Storage::exists($story->path) == true) {
|
||||
Storage::delete($story->path);
|
||||
}
|
||||
DB::transaction(function() use($story) {
|
||||
StoryView::whereStoryId($story->id)->delete();
|
||||
$story->delete();
|
||||
});
|
||||
}
|
||||
|
||||
$stories = Story::where('created_at', '<', now()
|
||||
->subMinutes(1441))
|
||||
->get();
|
||||
|
||||
if($stories->count() == 0) {
|
||||
exit;
|
||||
}
|
||||
|
||||
foreach($stories as $story) {
|
||||
if(Storage::exists($story->path) == true) {
|
||||
Storage::delete($story->path);
|
||||
}
|
||||
DB::transaction(function() use($story) {
|
||||
StoryView::whereStoryId($story->id)->delete();
|
||||
$story->delete();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,11 @@ class Handler extends ExceptionHandler
|
|||
*/
|
||||
public function render($request, Throwable $exception)
|
||||
{
|
||||
if ($request->wantsJson())
|
||||
return response()->json(
|
||||
['error' => $exception->getMessage()],
|
||||
method_exists($exception, 'getStatusCode') ? $exception->getStatusCode() : 500
|
||||
);
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -960,7 +960,7 @@ class ApiV1Controller extends Controller
|
|||
$res = [
|
||||
'approval_required' => false,
|
||||
'contact_account' => null,
|
||||
'description' => 'Pixelfed - Photo sharing for everyone',
|
||||
'description' => config('instance.description'),
|
||||
'email' => config('instance.email'),
|
||||
'invites_enabled' => false,
|
||||
'rules' => [],
|
||||
|
|
|
@ -12,7 +12,7 @@ use App\Services\StoryService;
|
|||
use Cache, Storage;
|
||||
use Image as Intervention;
|
||||
use App\Services\FollowerService;
|
||||
|
||||
use App\Services\MediaPathService;
|
||||
|
||||
class StoryController extends Controller
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ class StoryController extends Controller
|
|||
}
|
||||
|
||||
$photo = $request->file('file');
|
||||
$path = $this->storePhoto($photo);
|
||||
$path = $this->storePhoto($photo, $user);
|
||||
|
||||
$story = new Story();
|
||||
$story->duration = 3;
|
||||
|
@ -47,21 +47,18 @@ class StoryController extends Controller
|
|||
$story->path = $path;
|
||||
$story->local = true;
|
||||
$story->size = $photo->getSize();
|
||||
$story->expires_at = now()->addHours(24);
|
||||
$story->save();
|
||||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Successfully added',
|
||||
'media_id' => (string) $story->id,
|
||||
'media_url' => url(Storage::url($story->path))
|
||||
];
|
||||
}
|
||||
|
||||
protected function storePhoto($photo)
|
||||
protected function storePhoto($photo, $user)
|
||||
{
|
||||
$monthHash = substr(hash('sha1', date('Y').date('m')), 0, 12);
|
||||
$sid = (string) Str::uuid();
|
||||
$rid = Str::random(9).'.'.Str::random(9);
|
||||
$mimes = explode(',', config('pixelfed.media_types'));
|
||||
if(in_array($photo->getMimeType(), [
|
||||
'image/jpeg',
|
||||
|
@ -72,9 +69,9 @@ class StoryController extends Controller
|
|||
return;
|
||||
}
|
||||
|
||||
$storagePath = "public/_esm.t2/{$monthHash}/{$sid}/{$rid}";
|
||||
$storagePath = MediaPathService::story($user->profile);
|
||||
$path = $photo->store($storagePath);
|
||||
if(in_array($photo->getMimeType(), ['image/jpeg','image/png',])) {
|
||||
if(in_array($photo->getMimeType(), ['image/jpeg','image/png'])) {
|
||||
$fpath = storage_path('app/' . $path);
|
||||
$img = Intervention::make($fpath);
|
||||
$img->orientate();
|
||||
|
@ -84,6 +81,68 @@ class StoryController extends Controller
|
|||
return $path;
|
||||
}
|
||||
|
||||
public function cropPhoto(Request $request)
|
||||
{
|
||||
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'media_id' => 'required|integer|min:1',
|
||||
'width' => 'required',
|
||||
'height' => 'required',
|
||||
'x' => 'required',
|
||||
'y' => 'required'
|
||||
]);
|
||||
|
||||
$user = $request->user();
|
||||
$id = $request->input('media_id');
|
||||
$width = round($request->input('width'));
|
||||
$height = round($request->input('height'));
|
||||
$x = round($request->input('x'));
|
||||
$y = round($request->input('y'));
|
||||
|
||||
$story = Story::whereProfileId($user->profile_id)->findOrFail($id);
|
||||
|
||||
$path = storage_path('app/' . $story->path);
|
||||
|
||||
if(!is_file($path)) {
|
||||
abort(400, 'Invalid or missing media.');
|
||||
}
|
||||
|
||||
$img = Intervention::make($path);
|
||||
$img->crop($width, $height, $x, $y);
|
||||
$img->save($path, config('pixelfed.image_quality'));
|
||||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Successfully cropped',
|
||||
];
|
||||
}
|
||||
|
||||
public function publishStory(Request $request)
|
||||
{
|
||||
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$this->validate($request, [
|
||||
'media_id' => 'required',
|
||||
'duration' => 'required|integer|min:3|max:10'
|
||||
]);
|
||||
|
||||
$id = $request->input('media_id');
|
||||
$user = $request->user();
|
||||
$story = Story::whereProfileId($user->profile_id)
|
||||
->findOrFail($id);
|
||||
|
||||
$story->active = true;
|
||||
$story->duration = $request->input('duration', 10);
|
||||
$story->expires_at = now()->addHours(24);
|
||||
$story->save();
|
||||
|
||||
return [
|
||||
'code' => 200,
|
||||
'msg' => 'Successfully published',
|
||||
];
|
||||
}
|
||||
|
||||
public function apiV1Delete(Request $request, $id)
|
||||
{
|
||||
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
@ -91,7 +150,7 @@ class StoryController extends Controller
|
|||
$user = $request->user();
|
||||
|
||||
$story = Story::whereProfileId($user->profile_id)
|
||||
->findOrFail($id);
|
||||
->findOrFail($id);
|
||||
|
||||
if(Storage::exists($story->path) == true) {
|
||||
Storage::delete($story->path);
|
||||
|
@ -114,6 +173,7 @@ class StoryController extends Controller
|
|||
|
||||
if(config('database.default') == 'pgsql') {
|
||||
$db = Story::with('profile')
|
||||
->whereActive(true)
|
||||
->whereIn('profile_id', $following)
|
||||
->where('expires_at', '>', now())
|
||||
->distinct('profile_id')
|
||||
|
@ -121,8 +181,9 @@ class StoryController extends Controller
|
|||
->get();
|
||||
} else {
|
||||
$db = Story::with('profile')
|
||||
->whereActive(true)
|
||||
->whereIn('profile_id', $following)
|
||||
->where('expires_at', '>', now())
|
||||
->where('created_at', '>', now()->subDay())
|
||||
->orderByDesc('expires_at')
|
||||
->groupBy('profile_id')
|
||||
->take(9)
|
||||
|
@ -158,6 +219,7 @@ class StoryController extends Controller
|
|||
}
|
||||
|
||||
$stories = Story::whereProfileId($profile->id)
|
||||
->whereActive(true)
|
||||
->orderBy('expires_at', 'desc')
|
||||
->where('expires_at', '>', now())
|
||||
->when(!$publicOnly, function($query, $publicOnly) {
|
||||
|
@ -187,6 +249,7 @@ class StoryController extends Controller
|
|||
|
||||
$authed = $request->user()->profile;
|
||||
$story = Story::with('profile')
|
||||
->whereActive(true)
|
||||
->where('expires_at', '>', now())
|
||||
->findOrFail($id);
|
||||
|
||||
|
@ -198,11 +261,11 @@ class StoryController extends Controller
|
|||
}
|
||||
|
||||
abort_if(!$publicOnly, 403);
|
||||
|
||||
|
||||
$res = [
|
||||
'id' => (string) $story->id,
|
||||
'type' => Str::endsWith($story->path, '.mp4') ? 'video' :'photo',
|
||||
'length' => 3,
|
||||
'length' => 10,
|
||||
'src' => url(Storage::url($story->path)),
|
||||
'preview' => null,
|
||||
'link' => null,
|
||||
|
@ -227,6 +290,7 @@ class StoryController extends Controller
|
|||
}
|
||||
|
||||
$stories = Story::whereProfileId($profile->id)
|
||||
->whereActive(true)
|
||||
->orderBy('expires_at')
|
||||
->where('expires_at', '>', now())
|
||||
->when(!$publicOnly, function($query, $publicOnly) {
|
||||
|
@ -237,7 +301,7 @@ class StoryController extends Controller
|
|||
return [
|
||||
'id' => $s->id,
|
||||
'type' => Str::endsWith($s->path, '.mp4') ? 'video' :'photo',
|
||||
'length' => 3,
|
||||
'length' => 10,
|
||||
'src' => url(Storage::url($s->path)),
|
||||
'preview' => null,
|
||||
'link' => null,
|
||||
|
@ -272,19 +336,21 @@ class StoryController extends Controller
|
|||
'id' => 'required|integer|min:1|exists:stories',
|
||||
]);
|
||||
$id = $request->input('id');
|
||||
|
||||
$authed = $request->user()->profile;
|
||||
|
||||
$story = Story::with('profile')
|
||||
->where('expires_at', '>', now())
|
||||
->orderByDesc('expires_at')
|
||||
->findOrFail($id);
|
||||
|
||||
$profile = $story->profile;
|
||||
|
||||
if($story->profile_id == $authed->id) {
|
||||
$publicOnly = true;
|
||||
} else {
|
||||
$publicOnly = (bool) $profile->followedBy($authed);
|
||||
return [];
|
||||
}
|
||||
|
||||
$publicOnly = (bool) $profile->followedBy($authed);
|
||||
abort_if(!$publicOnly, 403);
|
||||
|
||||
StoryView::firstOrCreate([
|
||||
|
@ -292,6 +358,9 @@ class StoryController extends Controller
|
|||
'profile_id' => $authed->id
|
||||
]);
|
||||
|
||||
$story->view_count = $story->view_count + 1;
|
||||
$story->save();
|
||||
|
||||
return ['code' => 200];
|
||||
}
|
||||
|
||||
|
@ -300,6 +369,7 @@ class StoryController extends Controller
|
|||
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
$res = (bool) Story::whereProfileId($id)
|
||||
->whereActive(true)
|
||||
->where('expires_at', '>', now())
|
||||
->count();
|
||||
|
||||
|
@ -312,6 +382,7 @@ class StoryController extends Controller
|
|||
|
||||
$profile = $request->user()->profile;
|
||||
$stories = Story::whereProfileId($profile->id)
|
||||
->whereActive(true)
|
||||
->orderBy('expires_at')
|
||||
->where('expires_at', '>', now())
|
||||
->get()
|
||||
|
@ -346,7 +417,7 @@ class StoryController extends Controller
|
|||
public function compose(Request $request)
|
||||
{
|
||||
abort_if(!config('instance.stories.enabled') || !$request->user(), 404);
|
||||
|
||||
|
||||
return view('stories.compose');
|
||||
}
|
||||
|
||||
|
|
|
@ -12,116 +12,120 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use App\Jobs\ImageOptimizePipeline\ImageOptimize;
|
||||
use App\{
|
||||
ImportJob,
|
||||
ImportData,
|
||||
Media,
|
||||
Profile,
|
||||
Status,
|
||||
ImportJob,
|
||||
ImportData,
|
||||
Media,
|
||||
Profile,
|
||||
Status,
|
||||
};
|
||||
|
||||
class ImportInstagram implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
protected $import;
|
||||
|
||||
/**
|
||||
* Delete the job if its models no longer exist.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ImportJob $import)
|
||||
{
|
||||
$this->import = $import;
|
||||
}
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if(config('pixelfed.import.instagram.enabled') != true) {
|
||||
return;
|
||||
}
|
||||
protected $import;
|
||||
|
||||
$job = ImportJob::findOrFail($this->import->id);
|
||||
$profile = Profile::findOrFail($job->profile_id);
|
||||
$user = $profile->user;
|
||||
$json = $job->mediaJson();
|
||||
$collection = array_reverse($json['photos']);
|
||||
$files = $job->files;
|
||||
$monthHash = hash('sha1', date('Y').date('m'));
|
||||
$userHash = hash('sha1', $user->id . (string) $user->created_at);
|
||||
$fs = new Filesystem;
|
||||
/**
|
||||
* Delete the job if its models no longer exist.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $deleteWhenMissingModels = true;
|
||||
|
||||
foreach($collection as $import)
|
||||
{
|
||||
$caption = $import['caption'];
|
||||
try {
|
||||
$min = Carbon::create(2010, 10, 6, 0, 0, 0);
|
||||
$taken_at = Carbon::parse($import['taken_at']);
|
||||
if(!$min->lt($taken_at)) {
|
||||
$taken_at = Carbon::now();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
||||
}
|
||||
$filename = last( explode('/', $import['path']) );
|
||||
$importData = ImportData::whereJobId($job->id)
|
||||
->whereOriginalName($filename)
|
||||
->first();
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(ImportJob $import)
|
||||
{
|
||||
$this->import = $import;
|
||||
}
|
||||
|
||||
if(empty($importData) || is_file(storage_path("app/$importData->path")) == false) {
|
||||
continue;
|
||||
}
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if(config('pixelfed.import.instagram.enabled') != true) {
|
||||
return;
|
||||
}
|
||||
|
||||
DB::transaction(function() use(
|
||||
$fs, $job, $profile, $caption, $taken_at, $filename,
|
||||
$monthHash, $userHash, $importData
|
||||
) {
|
||||
$status = new Status();
|
||||
$status->profile_id = $profile->id;
|
||||
$status->caption = strip_tags($caption);
|
||||
$status->is_nsfw = false;
|
||||
$status->type = 'photo';
|
||||
$status->scope = 'unlisted';
|
||||
$status->visibility = 'unlisted';
|
||||
$status->created_at = $taken_at;
|
||||
$status->save();
|
||||
$job = ImportJob::findOrFail($this->import->id);
|
||||
$profile = Profile::findOrFail($job->profile_id);
|
||||
$user = $profile->user;
|
||||
$json = $job->mediaJson();
|
||||
$collection = array_reverse($json['photos']);
|
||||
$files = $job->files;
|
||||
$monthHash = hash('sha1', date('Y').date('m'));
|
||||
$userHash = hash('sha1', $user->id . (string) $user->created_at);
|
||||
$fs = new Filesystem;
|
||||
|
||||
foreach($collection as $import)
|
||||
{
|
||||
$caption = $import['caption'];
|
||||
try {
|
||||
$min = Carbon::create(2010, 10, 6, 0, 0, 0);
|
||||
$taken_at = Carbon::parse($import['taken_at']);
|
||||
if(!$min->lt($taken_at)) {
|
||||
$taken_at = Carbon::now();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
|
||||
}
|
||||
$filename = last( explode('/', $import['path']) );
|
||||
$importData = ImportData::whereJobId($job->id)
|
||||
->whereOriginalName($filename)
|
||||
->first();
|
||||
|
||||
if(empty($importData) || is_file(storage_path("app/$importData->path")) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::transaction(function() use(
|
||||
$fs, $job, $profile, $caption, $taken_at, $filename,
|
||||
$monthHash, $userHash, $importData
|
||||
) {
|
||||
$status = new Status();
|
||||
$status->profile_id = $profile->id;
|
||||
$status->caption = strip_tags($caption);
|
||||
$status->is_nsfw = false;
|
||||
$status->type = 'photo';
|
||||
$status->scope = 'unlisted';
|
||||
$status->visibility = 'unlisted';
|
||||
$status->created_at = $taken_at;
|
||||
$status->save();
|
||||
|
||||
|
||||
$path = storage_path("app/$importData->path");
|
||||
$storagePath = "public/m/{$monthHash}/{$userHash}";
|
||||
$newPath = "app/$storagePath/$filename";
|
||||
$fs->move($path,storage_path($newPath));
|
||||
$path = $newPath;
|
||||
$hash = \hash_file('sha256', storage_path($path));
|
||||
$media = new Media();
|
||||
$media->status_id = $status->id;
|
||||
$media->profile_id = $profile->id;
|
||||
$media->user_id = $profile->user->id;
|
||||
$media->media_path = "$storagePath/$filename";
|
||||
$media->original_sha256 = $hash;
|
||||
$media->size = $fs->size(storage_path($path));
|
||||
$media->mime = $fs->mimeType(storage_path($path));
|
||||
$media->filter_class = null;
|
||||
$media->filter_name = null;
|
||||
$media->order = 1;
|
||||
$media->save();
|
||||
ImageOptimize::dispatch($media);
|
||||
});
|
||||
}
|
||||
$path = storage_path("app/$importData->path");
|
||||
$storagePath = "public/m/{$monthHash}/{$userHash}";
|
||||
$dir = "app/$storagePath";
|
||||
if(!is_dir(storage_path($dir))) {
|
||||
mkdir(storage_path($dir), 0755, true);
|
||||
}
|
||||
$newPath = "$dir/$filename";
|
||||
$fs->move($path,storage_path($newPath));
|
||||
$path = $newPath;
|
||||
$hash = \hash_file('sha256', storage_path($path));
|
||||
$media = new Media();
|
||||
$media->status_id = $status->id;
|
||||
$media->profile_id = $profile->id;
|
||||
$media->user_id = $profile->user->id;
|
||||
$media->media_path = "$storagePath/$filename";
|
||||
$media->original_sha256 = $hash;
|
||||
$media->size = $fs->size(storage_path($path));
|
||||
$media->mime = $fs->mimeType(storage_path($path));
|
||||
$media->filter_class = null;
|
||||
$media->filter_name = null;
|
||||
$media->order = 1;
|
||||
$media->save();
|
||||
ImageOptimize::dispatch($media);
|
||||
});
|
||||
}
|
||||
|
||||
$job->completed_at = Carbon::now();
|
||||
$job->save();
|
||||
}
|
||||
$job->completed_at = Carbon::now();
|
||||
$job->save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,12 +176,14 @@ class Helpers {
|
|||
}
|
||||
}
|
||||
|
||||
$bannedInstances = InstanceService::getBannedDomains();
|
||||
|
||||
if(in_array($host, $bannedInstances)) {
|
||||
return false;
|
||||
if(app()->environment() === 'production') {
|
||||
$bannedInstances = InstanceService::getBannedDomains();
|
||||
if(in_array($host, $bannedInstances)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(in_array($host, $localhosts)) {
|
||||
return false;
|
||||
}
|
||||
|
|
193
composer.lock
generated
193
composer.lock
generated
|
@ -130,16 +130,16 @@
|
|||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.178.6",
|
||||
"version": "3.179.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "0aa83b522d5ffa794c02e7411af87a0e241a3082"
|
||||
"reference": "f4f2c01b53f71379a1ed8ccccf4305949a69ccbe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/0aa83b522d5ffa794c02e7411af87a0e241a3082",
|
||||
"reference": "0aa83b522d5ffa794c02e7411af87a0e241a3082",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f4f2c01b53f71379a1ed8ccccf4305949a69ccbe",
|
||||
"reference": "f4f2c01b53f71379a1ed8ccccf4305949a69ccbe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -214,9 +214,9 @@
|
|||
"support": {
|
||||
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
|
||||
"issues": "https://github.com/aws/aws-sdk-php/issues",
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.178.6"
|
||||
"source": "https://github.com/aws/aws-sdk-php/tree/3.179.1"
|
||||
},
|
||||
"time": "2021-04-19T18:13:17+00:00"
|
||||
"time": "2021-04-29T18:17:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
|
@ -656,40 +656,39 @@
|
|||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "1.10.2",
|
||||
"version": "1.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/cache.git",
|
||||
"reference": "13e3381b25847283a91948d04640543941309727"
|
||||
"reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/13e3381b25847283a91948d04640543941309727",
|
||||
"reference": "13e3381b25847283a91948d04640543941309727",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/a9c1b59eba5a08ca2770a76eddb88922f504e8e0",
|
||||
"reference": "a9c1b59eba5a08ca2770a76eddb88922f504e8e0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": ">2.2,<2.4"
|
||||
"doctrine/common": ">2.2,<2.4",
|
||||
"psr/cache": ">=3"
|
||||
},
|
||||
"require-dev": {
|
||||
"alcaeus/mongo-php-adapter": "^1.1",
|
||||
"doctrine/coding-standard": "^6.0",
|
||||
"cache/integration-tests": "dev-master",
|
||||
"doctrine/coding-standard": "^8.0",
|
||||
"mongodb/mongodb": "^1.1",
|
||||
"phpunit/phpunit": "^7.0",
|
||||
"predis/predis": "~1.0"
|
||||
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
|
||||
"predis/predis": "~1.0",
|
||||
"psr/cache": "^1.0 || ^2.0",
|
||||
"symfony/cache": "^4.4 || ^5.2"
|
||||
},
|
||||
"suggest": {
|
||||
"alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.9.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache"
|
||||
|
@ -736,7 +735,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/cache/issues",
|
||||
"source": "https://github.com/doctrine/cache/tree/1.10.x"
|
||||
"source": "https://github.com/doctrine/cache/tree/1.11.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -752,7 +751,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-07-07T18:54:01+00:00"
|
||||
"time": "2021-04-13T14:46:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/dbal",
|
||||
|
@ -1517,16 +1516,16 @@
|
|||
},
|
||||
{
|
||||
"name": "fruitcake/laravel-cors",
|
||||
"version": "v2.0.3",
|
||||
"version": "v2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruitcake/laravel-cors.git",
|
||||
"reference": "01de0fe5f71c70d1930ee9a80385f9cc28e0f63a"
|
||||
"reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/01de0fe5f71c70d1930ee9a80385f9cc28e0f63a",
|
||||
"reference": "01de0fe5f71c70d1930ee9a80385f9cc28e0f63a",
|
||||
"url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/a8ccedc7ca95189ead0e407c43b530dc17791d6a",
|
||||
"reference": "a8ccedc7ca95189ead0e407c43b530dc17791d6a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1539,8 +1538,8 @@
|
|||
},
|
||||
"require-dev": {
|
||||
"laravel/framework": "^6|^7|^8",
|
||||
"orchestra/testbench-dusk": "^4|^5|^6",
|
||||
"phpunit/phpunit": "^6|^7|^8",
|
||||
"orchestra/testbench-dusk": "^4|^5|^6|^7",
|
||||
"phpunit/phpunit": "^6|^7|^8|^9",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -1582,7 +1581,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/fruitcake/laravel-cors/issues",
|
||||
"source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.3"
|
||||
"source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -1590,7 +1589,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-10-22T13:57:20+00:00"
|
||||
"time": "2021-04-26T11:24:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "geerlingguy/ping",
|
||||
|
@ -1823,16 +1822,16 @@
|
|||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.8.1",
|
||||
"version": "1.8.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "35ea11d335fd638b5882ff1725228b3d35496ab1"
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1",
|
||||
"reference": "35ea11d335fd638b5882ff1725228b3d35496ab1",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"reference": "dc960a912984efb74d0a90222870c72c87f10c91",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -1892,9 +1891,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/guzzle/psr7/issues",
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.1"
|
||||
"source": "https://github.com/guzzle/psr7/tree/1.8.2"
|
||||
},
|
||||
"time": "2021-03-21T16:25:00+00:00"
|
||||
"time": "2021-04-26T09:17:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "intervention/image",
|
||||
|
@ -2107,16 +2106,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/framework",
|
||||
"version": "v8.38.0",
|
||||
"version": "v8.40.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/framework.git",
|
||||
"reference": "26a73532c54d2c090692bf2e3e64e449669053ba"
|
||||
"reference": "a654897ad7f97aea9d7ef292803939798c4a02a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/26a73532c54d2c090692bf2e3e64e449669053ba",
|
||||
"reference": "26a73532c54d2c090692bf2e3e64e449669053ba",
|
||||
"url": "https://api.github.com/repos/laravel/framework/zipball/a654897ad7f97aea9d7ef292803939798c4a02a4",
|
||||
"reference": "a654897ad7f97aea9d7ef292803939798c4a02a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2271,7 +2270,7 @@
|
|||
"issues": "https://github.com/laravel/framework/issues",
|
||||
"source": "https://github.com/laravel/framework"
|
||||
},
|
||||
"time": "2021-04-20T13:50:21+00:00"
|
||||
"time": "2021-04-28T14:38:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/helpers",
|
||||
|
@ -2331,16 +2330,16 @@
|
|||
},
|
||||
{
|
||||
"name": "laravel/horizon",
|
||||
"version": "v5.7.5",
|
||||
"version": "v5.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/horizon.git",
|
||||
"reference": "9bf0ef4873d9e52f58a9cd1de69dcdd98a5c4fe8"
|
||||
"reference": "24ffd819df749ef11a4eb20e14150b671d4f5717"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/9bf0ef4873d9e52f58a9cd1de69dcdd98a5c4fe8",
|
||||
"reference": "9bf0ef4873d9e52f58a9cd1de69dcdd98a5c4fe8",
|
||||
"url": "https://api.github.com/repos/laravel/horizon/zipball/24ffd819df749ef11a4eb20e14150b671d4f5717",
|
||||
"reference": "24ffd819df749ef11a4eb20e14150b671d4f5717",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2402,9 +2401,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/horizon/issues",
|
||||
"source": "https://github.com/laravel/horizon/tree/v5.7.5"
|
||||
"source": "https://github.com/laravel/horizon/tree/v5.7.6"
|
||||
},
|
||||
"time": "2021-04-06T14:17:52+00:00"
|
||||
"time": "2021-04-27T18:00:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/passport",
|
||||
|
@ -3913,16 +3912,16 @@
|
|||
},
|
||||
{
|
||||
"name": "pbmedia/laravel-ffmpeg",
|
||||
"version": "7.5.10",
|
||||
"version": "7.5.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/protonemedia/laravel-ffmpeg.git",
|
||||
"reference": "d3c3b77e5de08d4038ebcb9e9d405d51ec8ce2f9"
|
||||
"reference": "95b75f41edce12f513df12928b10b8f6949ffe56"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/protonemedia/laravel-ffmpeg/zipball/d3c3b77e5de08d4038ebcb9e9d405d51ec8ce2f9",
|
||||
"reference": "d3c3b77e5de08d4038ebcb9e9d405d51ec8ce2f9",
|
||||
"url": "https://api.github.com/repos/protonemedia/laravel-ffmpeg/zipball/95b75f41edce12f513df12928b10b8f6949ffe56",
|
||||
"reference": "95b75f41edce12f513df12928b10b8f6949ffe56",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -3934,7 +3933,7 @@
|
|||
"illuminate/support": "^6.0|^7.0|^8.0",
|
||||
"league/flysystem": "^1.0.34",
|
||||
"php": "^7.3|^8.0",
|
||||
"php-ffmpeg/php-ffmpeg": "^0.17.0|^0.18.0"
|
||||
"php-ffmpeg/php-ffmpeg": "^0.18.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"league/flysystem-memory": "^1.0",
|
||||
|
@ -3986,7 +3985,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/protonemedia/laravel-ffmpeg/issues",
|
||||
"source": "https://github.com/protonemedia/laravel-ffmpeg/tree/7.5.10"
|
||||
"source": "https://github.com/protonemedia/laravel-ffmpeg/tree/7.5.11"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -3994,7 +3993,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-31T14:18:52+00:00"
|
||||
"time": "2021-04-25T20:47:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-ffmpeg/php-ffmpeg",
|
||||
|
@ -5315,16 +5314,16 @@
|
|||
},
|
||||
{
|
||||
"name": "spatie/image-optimizer",
|
||||
"version": "1.3.2",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/image-optimizer.git",
|
||||
"reference": "6aa170eb292758553d332efee5e0c3977341080c"
|
||||
"reference": "c22202fdd57856ed18a79cfab522653291a6e96a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/image-optimizer/zipball/6aa170eb292758553d332efee5e0c3977341080c",
|
||||
"reference": "6aa170eb292758553d332efee5e0c3977341080c",
|
||||
"url": "https://api.github.com/repos/spatie/image-optimizer/zipball/c22202fdd57856ed18a79cfab522653291a6e96a",
|
||||
"reference": "c22202fdd57856ed18a79cfab522653291a6e96a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5363,9 +5362,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/image-optimizer/issues",
|
||||
"source": "https://github.com/spatie/image-optimizer/tree/1.3.2"
|
||||
"source": "https://github.com/spatie/image-optimizer/tree/1.4.0"
|
||||
},
|
||||
"time": "2020-11-28T12:37:58+00:00"
|
||||
"time": "2021-04-22T06:17:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/laravel-backup",
|
||||
|
@ -8287,16 +8286,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "brianium/paratest",
|
||||
"version": "v6.2.0",
|
||||
"version": "v6.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paratestphp/paratest.git",
|
||||
"reference": "9a94366983ce32c7724fc92e3b544327d4adb9be"
|
||||
"reference": "268d5b2b4237c0abf76c4aa9633ad8580be01e1e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/9a94366983ce32c7724fc92e3b544327d4adb9be",
|
||||
"reference": "9a94366983ce32c7724fc92e3b544327d4adb9be",
|
||||
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/268d5b2b4237c0abf76c4aa9633ad8580be01e1e",
|
||||
"reference": "268d5b2b4237c0abf76c4aa9633ad8580be01e1e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8305,28 +8304,28 @@
|
|||
"ext-reflection": "*",
|
||||
"ext-simplexml": "*",
|
||||
"php": "^7.3 || ^8.0",
|
||||
"phpunit/php-code-coverage": "^9.2.5",
|
||||
"phpunit/php-code-coverage": "^9.2.6",
|
||||
"phpunit/php-file-iterator": "^3.0.5",
|
||||
"phpunit/php-timer": "^5.0.3",
|
||||
"phpunit/phpunit": "^9.5.1",
|
||||
"phpunit/phpunit": "^9.5.4",
|
||||
"sebastian/environment": "^5.1.3",
|
||||
"symfony/console": "^4.4 || ^5.2",
|
||||
"symfony/process": "^4.4 || ^5.2"
|
||||
"symfony/console": "^4.4.21 || ^5.2.6",
|
||||
"symfony/process": "^4.4.21 || ^5.2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^8.2.0",
|
||||
"ekino/phpstan-banned-code": "^0.3.1",
|
||||
"doctrine/coding-standard": "^9.0.0",
|
||||
"ekino/phpstan-banned-code": "^0.4.0",
|
||||
"ergebnis/phpstan-rules": "^0.15.3",
|
||||
"ext-posix": "*",
|
||||
"infection/infection": "^0.20.2",
|
||||
"phpstan/phpstan": "^0.12.70",
|
||||
"infection/infection": "^0.21.5",
|
||||
"phpstan/phpstan": "^0.12.84",
|
||||
"phpstan/phpstan-deprecation-rules": "^0.12.6",
|
||||
"phpstan/phpstan-phpunit": "^0.12.17",
|
||||
"phpstan/phpstan-phpunit": "^0.12.18",
|
||||
"phpstan/phpstan-strict-rules": "^0.12.9",
|
||||
"squizlabs/php_codesniffer": "^3.5.8",
|
||||
"symfony/filesystem": "^5.2.2",
|
||||
"squizlabs/php_codesniffer": "^3.6.0",
|
||||
"symfony/filesystem": "^5.2.6",
|
||||
"thecodingmachine/phpstan-strict-rules": "^0.12.1",
|
||||
"vimeo/psalm": "^4.4.1"
|
||||
"vimeo/psalm": "^4.7.1"
|
||||
},
|
||||
"bin": [
|
||||
"bin/paratest"
|
||||
|
@ -8347,8 +8346,12 @@
|
|||
{
|
||||
"name": "Brian Scaturro",
|
||||
"email": "scaturrob@gmail.com",
|
||||
"homepage": "http://brianscaturro.com",
|
||||
"role": "Lead"
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Filippo Tessarotto",
|
||||
"email": "zoeslam@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Parallel testing for PHP",
|
||||
|
@ -8361,9 +8364,19 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/paratestphp/paratest/issues",
|
||||
"source": "https://github.com/paratestphp/paratest/tree/v6.2.0"
|
||||
"source": "https://github.com/paratestphp/paratest/tree/v6.3.0"
|
||||
},
|
||||
"time": "2021-01-29T15:25:31+00:00"
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/Slamdunk",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://paypal.me/filippotessarotto",
|
||||
"type": "paypal"
|
||||
}
|
||||
],
|
||||
"time": "2021-04-27T09:24:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
|
@ -8501,16 +8514,16 @@
|
|||
},
|
||||
{
|
||||
"name": "facade/ignition",
|
||||
"version": "2.8.3",
|
||||
"version": "2.8.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/facade/ignition.git",
|
||||
"reference": "a8201d51aae83addceaef9344592a3b068b5d64d"
|
||||
"reference": "87fb348dab0ae1a7c206c3e902a5a44ba541742f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/a8201d51aae83addceaef9344592a3b068b5d64d",
|
||||
"reference": "a8201d51aae83addceaef9344592a3b068b5d64d",
|
||||
"url": "https://api.github.com/repos/facade/ignition/zipball/87fb348dab0ae1a7c206c3e902a5a44ba541742f",
|
||||
"reference": "87fb348dab0ae1a7c206c3e902a5a44ba541742f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8574,7 +8587,7 @@
|
|||
"issues": "https://github.com/facade/ignition/issues",
|
||||
"source": "https://github.com/facade/ignition"
|
||||
},
|
||||
"time": "2021-04-09T20:45:59+00:00"
|
||||
"time": "2021-04-29T13:55:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facade/ignition-contracts",
|
||||
|
@ -8631,16 +8644,16 @@
|
|||
},
|
||||
{
|
||||
"name": "filp/whoops",
|
||||
"version": "2.12.0",
|
||||
"version": "2.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/filp/whoops.git",
|
||||
"reference": "d501fd2658d55491a2295ff600ae5978eaad7403"
|
||||
"reference": "c13c0be93cff50f88bbd70827d993026821914dd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/d501fd2658d55491a2295ff600ae5978eaad7403",
|
||||
"reference": "d501fd2658d55491a2295ff600ae5978eaad7403",
|
||||
"url": "https://api.github.com/repos/filp/whoops/zipball/c13c0be93cff50f88bbd70827d993026821914dd",
|
||||
"reference": "c13c0be93cff50f88bbd70827d993026821914dd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8690,7 +8703,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/filp/whoops/issues",
|
||||
"source": "https://github.com/filp/whoops/tree/2.12.0"
|
||||
"source": "https://github.com/filp/whoops/tree/2.12.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -8698,7 +8711,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-03-30T12:00:00+00:00"
|
||||
"time": "2021-04-25T12:00:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fzaninotto/faker",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
return [
|
||||
|
||||
'description' => env('INSTANCE_DESCRIPTION', null),
|
||||
'description' => env('INSTANCE_DESCRIPTION', 'Pixelfed - Photo sharing for everyone'),
|
||||
|
||||
'contact' => [
|
||||
'enabled' => env('INSTANCE_CONTACT_FORM', false),
|
||||
|
@ -18,7 +18,7 @@ return [
|
|||
'is_public' => env('INSTANCE_PUBLIC_HASHTAGS', false)
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
'email' => env('INSTANCE_CONTACT_EMAIL'),
|
||||
|
||||
'timeline' => [
|
||||
|
@ -72,4 +72,4 @@ return [
|
|||
'org' => env('COVID_LABEL_ORG', 'visit the WHO website')
|
||||
]
|
||||
],
|
||||
];
|
||||
];
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddActiveToStoriesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('stories', function (Blueprint $table) {
|
||||
$table->boolean('active')->nullable()->index();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('stories', function (Blueprint $table) {
|
||||
$table->dropColumn('active');
|
||||
});
|
||||
}
|
||||
}
|
BIN
public/css/app.css
vendored
BIN
public/css/app.css
vendored
Binary file not shown.
BIN
public/css/appdark.css
vendored
BIN
public/css/appdark.css
vendored
Binary file not shown.
BIN
public/css/landing.css
vendored
BIN
public/css/landing.css
vendored
Binary file not shown.
BIN
public/js/activity.js
vendored
BIN
public/js/activity.js
vendored
Binary file not shown.
BIN
public/js/collections.js
vendored
BIN
public/js/collections.js
vendored
Binary file not shown.
BIN
public/js/compose.js
vendored
BIN
public/js/compose.js
vendored
Binary file not shown.
BIN
public/js/direct.js
vendored
BIN
public/js/direct.js
vendored
Binary file not shown.
BIN
public/js/hashtag.js
vendored
BIN
public/js/hashtag.js
vendored
Binary file not shown.
BIN
public/js/network-timeline.js
vendored
BIN
public/js/network-timeline.js
vendored
Binary file not shown.
BIN
public/js/profile.js
vendored
BIN
public/js/profile.js
vendored
Binary file not shown.
BIN
public/js/rempos.js
vendored
BIN
public/js/rempos.js
vendored
Binary file not shown.
BIN
public/js/rempro.js
vendored
BIN
public/js/rempro.js
vendored
Binary file not shown.
BIN
public/js/search.js
vendored
BIN
public/js/search.js
vendored
Binary file not shown.
BIN
public/js/status.js
vendored
BIN
public/js/status.js
vendored
Binary file not shown.
BIN
public/js/story-compose.js
vendored
BIN
public/js/story-compose.js
vendored
Binary file not shown.
BIN
public/js/timeline.js
vendored
BIN
public/js/timeline.js
vendored
Binary file not shown.
BIN
public/js/vendor.js
vendored
BIN
public/js/vendor.js
vendored
Binary file not shown.
Binary file not shown.
|
@ -89,6 +89,7 @@
|
|||
<a v-if="!pageLoading && (page > 1 && page <= 2) || (page == 1 && ids.length != 0) || page == 'cropPhoto'" class="font-weight-bold text-decoration-none" href="#" @click.prevent="nextPage">Next</a>
|
||||
<a v-if="!pageLoading && page == 3" class="font-weight-bold text-decoration-none" href="#" @click.prevent="compose()">Post</a>
|
||||
<a v-if="!pageLoading && page == 'addText'" class="font-weight-bold text-decoration-none" href="#" @click.prevent="composeTextPost()">Post</a>
|
||||
<a v-if="!pageLoading && page == 'video-2'" class="font-weight-bold text-decoration-none" href="#" @click.prevent="compose()">Post</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -97,18 +98,20 @@
|
|||
<div class="list-group list-group-flush">
|
||||
<div
|
||||
v-for="(item, index) in availableLicenses"
|
||||
class="list-group-item cursor-pointer"
|
||||
:class="{
|
||||
'text-primary': licenseIndex === index,
|
||||
class="list-group-item cursor-pointer"
|
||||
:class="{
|
||||
'text-primary': licenseIndex === index,
|
||||
'font-weight-bold': licenseIndex === index
|
||||
}"
|
||||
}"
|
||||
@click="toggleLicense(index)">
|
||||
{{item.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="page == 'textOptions'" class="w-100 h-100" style="min-height: 280px;">
|
||||
</div>
|
||||
|
||||
<div v-if="page == 'addText'" class="w-100 h-100" style="min-height: 280px;">
|
||||
<div class="mt-2">
|
||||
<div class="media px-3">
|
||||
|
@ -148,10 +151,10 @@
|
|||
<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-bolt text-white fa-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0">
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Post</span>
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Post</span>
|
||||
</p>
|
||||
<p class="mb-0 text-muted">Share up to {{config.uploader.album_limit}} photos or videos</p>
|
||||
</div>
|
||||
|
@ -164,7 +167,7 @@
|
|||
<div class="media">
|
||||
<div class="mr-3 align-items-center justify-content-center" style="display:inline-flex;width:40px;height:40px;border-radius: 100%;border: 2px solid #008DF5">
|
||||
<i class="far fa-edit text-primary fa-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0">
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Text Post</span>
|
||||
|
@ -183,10 +186,10 @@
|
|||
<div class="media">
|
||||
<div class="mr-3 align-items-center justify-content-center" style="display:inline-flex;width:40px;height:40px;border-radius: 100%;border: 2px solid #008DF5">
|
||||
<i class="fas fa-history text-primary fa-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0">
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Story</span>
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Story</span>
|
||||
<sup class="float-right mt-2">
|
||||
<span class="btn btn-outline-lighter p-1 btn-sm font-weight-bold py-0" style="font-size:10px;line-height: 0.6">BETA</span>
|
||||
</sup>
|
||||
|
@ -202,10 +205,10 @@
|
|||
<div class="media">
|
||||
<div class="mr-3 align-items-center justify-content-center" style="display:inline-flex;width:40px;height:40px;border-radius: 100%;border: 2px solid #008DF5">
|
||||
<i class="fas fa-images text-primary fa-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0">
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Collection</span>
|
||||
<span class="h5 mt-0 font-weight-bold text-primary">New Collection</span>
|
||||
<sup class="float-right mt-2">
|
||||
<span class="btn btn-outline-lighter p-1 btn-sm font-weight-bold py-0" style="font-size:10px;line-height: 0.6">BETA</span>
|
||||
</sup>
|
||||
|
@ -216,7 +219,7 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
|
||||
|
||||
<p class="py-3">
|
||||
<a class="font-weight-bold" href="/site/help">Help</a>
|
||||
</p>
|
||||
|
@ -268,7 +271,7 @@
|
|||
<div class="nav-link" style="display:block;width:300px;height:300px;" @click="carouselCursor = i">
|
||||
<!-- <img :class="'d-block img-fluid w-100 ' + [m.filter_class?m.filter_class:'']" :src="m.url" :alt="m.description" :title="m.description"> -->
|
||||
<span :class="[m.filter_class?m.filter_class:'']">
|
||||
|
||||
|
||||
<span :class="'rounded border ' + [i == carouselCursor ? ' border-primary shadow':'']" :style="'display:block;padding:5px;width:100%;height:100%;background-image: url(' + m.url + ');background-size:cover;border-width:3px !important;'"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
@ -372,7 +375,7 @@
|
|||
</div>
|
||||
|
||||
<div v-if="page == 'tagPeople'" class="w-100 h-100 p-3">
|
||||
<autocomplete
|
||||
<autocomplete
|
||||
v-show="taggedUsernames.length < 10"
|
||||
:search="tagSearch"
|
||||
placeholder="@pixelfed"
|
||||
|
@ -413,7 +416,7 @@
|
|||
|
||||
<div v-if="page == 'addLocation'" class="w-100 h-100 p-3">
|
||||
<p class="mb-0">Add Location</p>
|
||||
<autocomplete
|
||||
<autocomplete
|
||||
:search="locationSearch"
|
||||
placeholder="Search locations ..."
|
||||
aria-label="Search locations ..."
|
||||
|
@ -501,21 +504,21 @@
|
|||
<div class="list-group list-group-flush">
|
||||
<div
|
||||
v-if="!profile.locked"
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'public' }"
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'public' }"
|
||||
@click="toggleVisibility('public')">
|
||||
Public
|
||||
</div>
|
||||
<div
|
||||
v-if="!profile.locked"
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'unlisted' }"
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'unlisted' }"
|
||||
@click="toggleVisibility('unlisted')">
|
||||
Unlisted
|
||||
</div>
|
||||
<div
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'private' }"
|
||||
<div
|
||||
class="list-group-item lead cursor-pointer"
|
||||
:class="{ 'text-primary': visibility == 'private' }"
|
||||
@click="toggleVisibility('private')">
|
||||
Followers Only
|
||||
</div>
|
||||
|
@ -589,7 +592,7 @@
|
|||
<span>{{media[carouselCursor].license ? media[carouselCursor].license.length : 0}}/140</span>
|
||||
</p> -->
|
||||
<select class="form-control" v-model="licenseIndex">
|
||||
<option
|
||||
<option
|
||||
v-for="(item, index) in availableLicenses"
|
||||
:value="index"
|
||||
:selected="index === licenseIndex">
|
||||
|
@ -606,6 +609,69 @@
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div v-if="page == 'video-2'" class="w-100 h-100">
|
||||
<div v-if="video.title.length" class="border-bottom">
|
||||
<div class="media p-3">
|
||||
<img :src="media[0].url" width="100px" height="70px" :class="[media[0].filter_class?'mr-2 ' + media[0].filter_class:'mr-2']">
|
||||
<div class="media-body">
|
||||
<p class="font-weight-bold mb-1">{{video.title ? video.title.slice(0,70) : 'Untitled'}}</p>
|
||||
<p class="mb-0 text-muted small">{{video.description ? video.description.slice(0,90) : 'No description'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="border-bottom d-flex justify-content-between px-4 mb-0 py-2 ">
|
||||
<div>
|
||||
<div class="text-dark ">Contains NSFW Media</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="custom-control custom-switch" style="z-index: 9999;">
|
||||
<input type="checkbox" class="custom-control-input" id="asnsfw" v-model="nsfw">
|
||||
<label class="custom-control-label" for="asnsfw"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-bottom">
|
||||
<p class="px-4 mb-0 py-2 cursor-pointer" @click="showLicenseCard()">Add license</p>
|
||||
</div>
|
||||
<div class="border-bottom">
|
||||
<p class="px-4 mb-0 py-2">
|
||||
<span>Audience</span>
|
||||
<span class="float-right">
|
||||
<a href="#" @click.prevent="showVisibilityCard()" class="btn btn-outline-secondary btn-sm small mr-3 mt-n1 disabled" style="font-size:10px;padding:3px;text-transform: uppercase" disabled>{{visibilityTag}}</a>
|
||||
<a href="#" @click.prevent="showVisibilityCard()" class="text-decoration-none"><i class="fas fa-chevron-right fa-lg text-lighter"></i></a>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="p-3">
|
||||
<!-- <div class="card card-body shadow-none border d-flex justify-content-center align-items-center mb-3 p-5">
|
||||
<div class="d-flex align-items-center">
|
||||
<p class="mb-0 text-center">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</p>
|
||||
<p class="ml-3 mb-0 text-center font-weight-bold">
|
||||
Processing video
|
||||
</p>
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="form-group">
|
||||
<p class="small font-weight-bold text-muted mb-0">Title</p>
|
||||
<input class="form-control" v-model="video.title" placeholder="Add a good title">
|
||||
<p class="help-text mb-0 small text-muted">{{video.title.length}}/70</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-0">
|
||||
<p class="small font-weight-bold text-muted mb-0">Description</p>
|
||||
<textarea class="form-control" v-model="video.description" placeholder="Add an optional description" maxlength="5000" rows="5"></textarea>
|
||||
<p class="help-text mb-0 small text-muted">{{video.description.length}}/5000</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- card-footers -->
|
||||
|
@ -679,7 +745,7 @@ import VueTribute from 'vue-tribute'
|
|||
|
||||
export default {
|
||||
|
||||
components: {
|
||||
components: {
|
||||
VueCropper,
|
||||
Autocomplete,
|
||||
VueTribute
|
||||
|
@ -700,12 +766,16 @@ export default {
|
|||
carouselCursor: 0,
|
||||
uploading: false,
|
||||
uploadProgress: 100,
|
||||
composeType: false,
|
||||
mode: 'photo',
|
||||
modes: [
|
||||
'photo',
|
||||
'video',
|
||||
'plain'
|
||||
],
|
||||
page: 1,
|
||||
composeState: 'publish',
|
||||
visibility: 'public',
|
||||
visibilityTag: 'Public',
|
||||
nsfw: false,
|
||||
place: false,
|
||||
commentsDisabled: false,
|
||||
optimizeMedia: true,
|
||||
|
@ -810,15 +880,16 @@ export default {
|
|||
name: "Attribution-NonCommercial-NoDerivs"
|
||||
}
|
||||
],
|
||||
licenseIndex: 0
|
||||
licenseIndex: 0,
|
||||
video: {
|
||||
title: '',
|
||||
description: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.fetchProfile();
|
||||
if(this.config.uploader.media_types.includes('video/mp4') == false) {
|
||||
this.composeType = 'post'
|
||||
}
|
||||
this.filters = window.App.util.filters;
|
||||
},
|
||||
|
||||
|
@ -860,6 +931,7 @@ export default {
|
|||
this.pageTitle = 'New Text Post';
|
||||
this.page = 'addText';
|
||||
this.textMode = true;
|
||||
this.mode = 'text';
|
||||
},
|
||||
|
||||
mediaWatcher() {
|
||||
|
@ -910,7 +982,14 @@ export default {
|
|||
self.media.push(e.data);
|
||||
self.uploading = false;
|
||||
setTimeout(function() {
|
||||
self.page = 2;
|
||||
// if(type === 'video/mp4') {
|
||||
// self.pageTitle = 'Edit Video Details';
|
||||
// self.mode = 'video';
|
||||
// self.page = 'video-2';
|
||||
// } else {
|
||||
// self.page = 2;
|
||||
// }
|
||||
self.page = 3;
|
||||
}, 300);
|
||||
}).catch(function(e) {
|
||||
switch(e.response.status) {
|
||||
|
@ -951,7 +1030,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
let id = this.media[this.carouselCursor].id;
|
||||
|
||||
|
||||
axios.delete('/api/compose/v0/media/delete', {
|
||||
params: {
|
||||
id: id
|
||||
|
@ -1001,7 +1080,8 @@ export default {
|
|||
place: this.place,
|
||||
tagged: this.taggedUsernames,
|
||||
optimize_media: this.optimizeMedia,
|
||||
license: this.availableLicenses[this.licenseIndex].id
|
||||
license: this.availableLicenses[this.licenseIndex].id,
|
||||
video: this.video
|
||||
};
|
||||
axios.post('/api/compose/v0/publish', data)
|
||||
.then(res => {
|
||||
|
@ -1068,41 +1148,99 @@ export default {
|
|||
},
|
||||
|
||||
closeModal() {
|
||||
this.composeType = '';
|
||||
$('#composeModal').modal('hide');
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.pageTitle = '';
|
||||
|
||||
switch(this.page) {
|
||||
case 'addText':
|
||||
this.page = 1;
|
||||
|
||||
switch(this.mode) {
|
||||
case 'photo':
|
||||
switch(this.page) {
|
||||
case 'addText':
|
||||
this.page = 1;
|
||||
break;
|
||||
|
||||
case 'textOptions':
|
||||
this.page = 'addText';
|
||||
break;
|
||||
|
||||
case 'cropPhoto':
|
||||
case 'editMedia':
|
||||
this.page = 2;
|
||||
break;
|
||||
|
||||
case 'tagPeopleHelp':
|
||||
this.showTagCard();
|
||||
break;
|
||||
|
||||
case 'licensePicker':
|
||||
this.page = 3;
|
||||
break;
|
||||
|
||||
case 'video-2':
|
||||
this.page = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
this.namedPages.indexOf(this.page) != -1 ?
|
||||
this.page = 3 : this.page--;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'textOptions':
|
||||
this.page = 'addText';
|
||||
break;
|
||||
case 'video':
|
||||
switch(this.page) {
|
||||
case 'licensePicker':
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
|
||||
case 'cropPhoto':
|
||||
case 'editMedia':
|
||||
this.page = 2;
|
||||
break;
|
||||
case 'video-2':
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
|
||||
case 'tagPeopleHelp':
|
||||
this.showTagCard();
|
||||
break;
|
||||
|
||||
case 'licensePicker':
|
||||
this.page = 3;
|
||||
default:
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this.namedPages.indexOf(this.page) != -1 ?
|
||||
this.page = (this.textMode ? 'addText' : 3) :
|
||||
(this.textMode ? 'addText' : this.page--);
|
||||
switch(this.page) {
|
||||
case 'addText':
|
||||
this.page = 1;
|
||||
break;
|
||||
|
||||
case 'textOptions':
|
||||
this.page = 'addText';
|
||||
break;
|
||||
|
||||
case 'cropPhoto':
|
||||
case 'editMedia':
|
||||
this.page = 2;
|
||||
break;
|
||||
|
||||
case 'tagPeopleHelp':
|
||||
this.showTagCard();
|
||||
break;
|
||||
|
||||
case 'licensePicker':
|
||||
this.page = 3;
|
||||
break;
|
||||
|
||||
case 'video-2':
|
||||
this.page = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
this.namedPages.indexOf(this.page) != -1 ?
|
||||
this.page = (this.mode == 'text' ? 'addText' : 3) :
|
||||
(this.mode == 'text' ? 'addText' : this.page--);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
nextPage() {
|
||||
|
@ -1115,7 +1253,7 @@ export default {
|
|||
case 'cropPhoto':
|
||||
this.pageLoading = true;
|
||||
let self = this;
|
||||
this.$refs.cropper.getCroppedCanvas({
|
||||
this.$refs.cropper.getCroppedCanvas({
|
||||
maxWidth: 4096,
|
||||
maxHeight: 4096,
|
||||
fillColor: '#fff',
|
||||
|
@ -1199,8 +1337,22 @@ export default {
|
|||
|
||||
onSubmitLocation(result) {
|
||||
this.place = result;
|
||||
this.pageTitle = this.textMode ? 'New Text Post' : '';
|
||||
this.page = (this.textMode ? 'addText' : 3);
|
||||
switch(this.mode) {
|
||||
case 'photo':
|
||||
this.pageTitle = '';
|
||||
this.page = 3;
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
this.pageTitle = 'Edit Video Details';
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
this.pageTitle = 'New Text Post';
|
||||
this.page = 'addText';
|
||||
break;
|
||||
}
|
||||
return;
|
||||
},
|
||||
|
||||
|
@ -1227,8 +1379,23 @@ export default {
|
|||
}
|
||||
this.visibility = state;
|
||||
this.visibilityTag = tags[state];
|
||||
this.pageTitle = '';
|
||||
this.page = this.textMode ? 'addText' : 3;
|
||||
|
||||
switch(this.mode) {
|
||||
case 'photo':
|
||||
this.pageTitle = '';
|
||||
this.page = 3;
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
this.pageTitle = 'Edit Video Details';
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
this.pageTitle = 'New Text Post';
|
||||
this.page = 'addText';
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
showMediaDescriptionsCard() {
|
||||
|
@ -1350,9 +1517,24 @@ export default {
|
|||
|
||||
toggleLicense(index) {
|
||||
this.licenseIndex = index;
|
||||
this.pageTitle = '';
|
||||
this.page = 3;
|
||||
|
||||
switch(this.mode) {
|
||||
case 'photo':
|
||||
this.pageTitle = '';
|
||||
this.page = 3;
|
||||
break;
|
||||
|
||||
case 'video':
|
||||
this.pageTitle = 'Edit Video Details';
|
||||
this.page = 'video-2';
|
||||
break;
|
||||
|
||||
case 'text':
|
||||
this.pageTitle = 'New Text Post';
|
||||
this.page = 'addText';
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -1,60 +1,92 @@
|
|||
<template>
|
||||
<div class="container mt-2 mt-md-5">
|
||||
<div class="container mt-2 mt-md-5 bg-black">
|
||||
<input type="file" id="pf-dz" name="media" class="d-none file-input" v-bind:accept="config.mimes">
|
||||
<span class="fixed-top text-right m-3 cursor-pointer" @click="navigateTo()">
|
||||
<i class="fas fa-times fa-lg text-white"></i>
|
||||
</span>
|
||||
<div v-if="loaded" class="row">
|
||||
<div class="col-12 col-md-6 offset-md-3">
|
||||
<div class="col-12 col-md-6 offset-md-3 bg-dark rounded-lg">
|
||||
|
||||
<!-- LANDING -->
|
||||
<div v-if="page == 'landing'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;">
|
||||
<div class="text-center flex-fill mt-5 pt-5">
|
||||
<img src="/img/pixelfed-icon-grey.svg" width="60px" height="60px">
|
||||
<p class="font-weight-bold lead text-lighter mt-1">Stories</p>
|
||||
<!-- <p v-if="loaded" class="font-weight-bold small text-uppercase text-muted">
|
||||
<span>{{stories.length}} Active</span>
|
||||
<span class="px-2">|</span>
|
||||
<span>30K Views</span>
|
||||
</p> -->
|
||||
<div class="text-center flex-fill pt-3">
|
||||
<p class="text-muted font-weight-light mb-1">
|
||||
<i class="fas fa-history fa-5x"></i>
|
||||
</p>
|
||||
<p class="text-muted font-weight-bold mb-0">STORIES</p>
|
||||
</div>
|
||||
<div class="flex-fill py-4">
|
||||
<div class="card w-100 shadow-none">
|
||||
<div class="list-group">
|
||||
<div class="card w-100 shadow-none bg-transparent">
|
||||
<div class="list-group bg-transparent">
|
||||
<!-- <a class="list-group-item text-center lead text-decoration-none text-dark" href="#">Camera</a> -->
|
||||
<a class="list-group-item text-center lead text-decoration-none text-dark" href="#" @click.prevent="upload()">Add Photo</a>
|
||||
<a v-if="stories.length" class="list-group-item text-center lead text-decoration-none text-dark" href="#" @click.prevent="edit()">Edit</a>
|
||||
<a class="list-group-item bg-transparent lead text-decoration-none text-light font-weight-bold border-light" href="#" @click.prevent="upload()">
|
||||
<i class="fas fa-plus-square mr-2"></i>
|
||||
Add to Story
|
||||
</a>
|
||||
<a v-if="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()">
|
||||
<i class="far fa-clone mr-2"></i>
|
||||
My Story
|
||||
</a>
|
||||
<a v-if="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="viewMyStory()">
|
||||
<i class="fas fa-history mr-2"></i>
|
||||
View My Story
|
||||
</a>
|
||||
<!-- <a v-if="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()">
|
||||
<i class="fas fa-network-wired mr-1"></i>
|
||||
Audience
|
||||
</a> -->
|
||||
<!-- <a v-if="stories.length" class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()">
|
||||
<i class="far fa-chart-bar mr-2"></i>
|
||||
Stats
|
||||
</a> -->
|
||||
<!-- <a class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()">
|
||||
<i class="far fa-folder mr-2"></i>
|
||||
Archived
|
||||
</a> -->
|
||||
<!-- <a class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="#" @click.prevent="edit()">
|
||||
<i class="far fa-question-circle mr-2"></i>
|
||||
Help
|
||||
</a> -->
|
||||
<a class="list-group-item bg-transparent lead text-decoration-none text-lighter font-weight-bold border-muted" href="/">
|
||||
<i class="fas fa-arrow-left mr-2"></i>
|
||||
Go back
|
||||
</a>
|
||||
<!-- <a class="list-group-item text-center lead text-decoration-none text-dark" href="#">Options</a> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex-fill">
|
||||
<p class="text-lighter small text-uppercase">
|
||||
<!-- <p class="text-lighter small text-uppercase">
|
||||
<a href="/" class="text-muted font-weight-bold">Home</a>
|
||||
<span class="px-2 text-lighter">|</span>
|
||||
<a href="/i/my/story" class="text-muted font-weight-bold">View My Story</a>
|
||||
<span class="px-2 text-lighter">|</span>
|
||||
<a href="/site/help" class="text-muted font-weight-bold">Help</a>
|
||||
</p>
|
||||
</p> -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CROP -->
|
||||
<div v-if="page == 'crop'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 95vh;">
|
||||
<div class="text-center pt-5 mb-3 d-flex justify-content-between align-items-center">
|
||||
<div v-if="page == 'crop'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;">
|
||||
<div class="text-center py-3 d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<button class="btn btn-outline-lighter btn-sm py-0 px-md-3"><i class="pr-2 fas fa-chevron-left fa-sm"></i> Delete</button>
|
||||
<button class="btn btn-outline-lighter btn-sm py-1 px-md-3" @click="deleteCurrentStory()"><i class="pr-2 fas fa-chevron-left fa-sm"></i> Delete</button>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<img class="d-inline-block mr-2" src="/img/pixelfed-icon-grey.svg" width="30px" height="30px">
|
||||
<span class="font-weight-bold lead text-lighter">Stories</span>
|
||||
<div class="">
|
||||
<p class="text-muted font-weight-light mb-1">
|
||||
<i class="fas fa-history fa-5x"></i>
|
||||
</p>
|
||||
<p class="text-muted font-weight-bold mb-0">STORIES</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-outline-success btn-sm py-0 px-md-3">Crop <i class="pl-2 fas fa-chevron-right fa-sm"></i></button>
|
||||
<button class="btn btn-primary btn-sm py-1 px-md-3" @click="performCrop()">Crop <i class="pl-2 fas fa-chevron-right fa-sm"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<div class="card w-100 mt-3">
|
||||
<div class="card-body p-0">
|
||||
<vue-cropper
|
||||
ref="cropper"
|
||||
ref="croppa"
|
||||
:relativeZoom="cropper.zoom"
|
||||
:aspectRatio="cropper.aspectRatio"
|
||||
:viewMode="cropper.viewMode"
|
||||
|
@ -66,20 +98,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex-fill">
|
||||
<p class="text-lighter small text-uppercase pt-2">
|
||||
<!-- <a href="#" class="text-muted font-weight-bold">Home</a>
|
||||
<span class="px-2 text-lighter">|</span>
|
||||
<a href="#" class="text-muted font-weight-bold">View My Story</a>
|
||||
<span class="px-2 text-lighter">|</span> -->
|
||||
<a href="/site/help" class="text-muted font-weight-bold mb-0">Help</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ERROR -->
|
||||
<div v-if="page == 'error'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;">
|
||||
<p class="h3 mb-0">Oops!</p>
|
||||
<p class="h3 mb-0 text-light">Oops!</p>
|
||||
<p class="text-muted lead">An error occurred, please try again later.</p>
|
||||
<p class="text-muted mb-0">
|
||||
<a class="btn btn-outline-secondary py-0 px-5 font-weight-bold" href="/">Go back</a>
|
||||
|
@ -88,30 +111,63 @@
|
|||
|
||||
<!-- UPLOADING -->
|
||||
<div v-if="page == 'uploading'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;">
|
||||
<p v-if="uploadProgress != 100" class="display-4 mb-0">Uploading {{uploadProgress}}%</p>
|
||||
<p v-else class="display-4 mb-0">Publishing Story</p>
|
||||
<p v-if="uploadProgress != 100" class="display-4 mb-0 text-muted">Uploading {{uploadProgress}}%</p>
|
||||
<p v-else class="display-4 mb-0 text-muted">Processing ...</p>
|
||||
</div>
|
||||
|
||||
<div v-if="page == 'edit'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;">
|
||||
<div class="text-center flex-fill mt-5 pt-5">
|
||||
<img src="/img/pixelfed-icon-grey.svg" width="60px" height="60px">
|
||||
<p class="font-weight-bold lead text-lighter mt-1">Stories</p>
|
||||
<!-- CROPPING -->
|
||||
<div v-if="page == 'cropping'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;">
|
||||
<p class="display-4 mb-0 text-muted">Cropping ...</p>
|
||||
</div>
|
||||
|
||||
<!-- PREVIEW -->
|
||||
<div v-if="page == 'preview'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center align-items-center" style="height: 90vh;">
|
||||
<div>
|
||||
<div class="form-group">
|
||||
<label for="durationSlider" class="text-light lead font-weight-bold">Story Duration</label>
|
||||
<input type="range" class="custom-range" min="3" max="10" id="durationSlider" v-model="duration">
|
||||
<p class="help-text text-center">
|
||||
<span class="text-light">{{duration}} seconds</span>
|
||||
</p>
|
||||
</div>
|
||||
<hr class="my-3">
|
||||
<a class="btn btn-primary btn-block px-5 font-weight-bold my-3" href="#" @click.prevent="shareStoryToFollowers()">
|
||||
Share Story with followers
|
||||
</a>
|
||||
|
||||
<a class="btn btn-outline-muted btn-block px-5 font-weight-bold" href="/" @click.prevent="deleteCurrentStory()">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
<div class="flex-fill py-5">
|
||||
<div class="card w-100 shadow-none" style="max-height: 500px; overflow-y: auto">
|
||||
<!-- <a class="btn btn-outline-secondary btn-block px-5 font-weight-bold" href="#">
|
||||
Share Story with everyone
|
||||
</a> -->
|
||||
</div>
|
||||
|
||||
<!-- EDIT -->
|
||||
<div v-if="page == 'edit'" class="card card-body bg-transparent border-0 shadow-none d-flex justify-content-center" style="height: 90vh;">
|
||||
<div class="text-center flex-fill mt-5">
|
||||
<p class="text-muted font-weight-light mb-1">
|
||||
<i class="fas fa-history fa-5x"></i>
|
||||
</p>
|
||||
<p class="text-muted font-weight-bold mb-0">STORIES</p>
|
||||
</div>
|
||||
<div class="flex-fill py-4">
|
||||
<p class="lead font-weight-bold text-lighter">My Stories</p>
|
||||
<div class="card w-100 shadow-none bg-transparent" style="max-height: 50vh; overflow-y: scroll">
|
||||
<div class="list-group">
|
||||
<div v-for="(story, index) in stories" class="list-group-item text-center text-dark" href="#">
|
||||
<div v-for="(story, index) in stories" class="list-group-item bg-transparent text-center border-muted text-lighter" href="#">
|
||||
<div class="media align-items-center">
|
||||
<div class="mr-3 cursor-pointer" @click="showLightbox(story)">
|
||||
<img :src="story.src" class="img-fluid" width="70px" height="70px">
|
||||
<p class="small text-muted text-center mb-0">(expand)</p>
|
||||
<img :src="story.src" class="rounded-circle border" width="40px" height="40px" style="object-fit: cover;">
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p class="mb-0">Expires</p>
|
||||
<p class="mb-0 text-muted small"><span>{{expiresTimestamp(story.expires_at)}}</span></p>
|
||||
<div class="media-body text-left">
|
||||
<p class="mb-0 text-muted font-weight-bold"><span>{{story.created_ago}} ago</span></p>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
<button @click="deleteStory(story, index)" class="btn btn-danger btn-sm font-weight-bold text-uppercase">Delete</button>
|
||||
<div class="flex-grow-1 text-right">
|
||||
<button @click="deleteStory(story, index)" class="btn btn-link btn-sm">
|
||||
<i class="fas fa-trash-alt fa-lg text-muted"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -119,7 +175,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="flex-fill text-center">
|
||||
<a class="btn btn-outline-secondary py-0 px-5 font-weight-bold" href="/i/stories/new">Go back</a>
|
||||
<a class="btn btn-outline-secondary btn-block px-5 font-weight-bold" href="/i/stories/new" @click.prevent="goBack()">Go back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -130,18 +186,24 @@
|
|||
hide-header
|
||||
hide-footer
|
||||
centered
|
||||
size="lg"
|
||||
body-class="p-0"
|
||||
size="md"
|
||||
class="bg-transparent"
|
||||
body-class="p-0 bg-transparent"
|
||||
>
|
||||
<div v-if="lightboxMedia" class="w-100 h-100">
|
||||
<img :src="lightboxMedia.url" style="max-height: 100%; max-width: 100%">
|
||||
<div v-if="lightboxMedia" class="w-100 h-100 bg-transparent">
|
||||
<img :src="lightboxMedia.url" style="max-height: 90vh; width: 100%; object-fit: contain;">
|
||||
</div>
|
||||
</b-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style type="text/css" scoped>
|
||||
|
||||
<style type="text/css">
|
||||
.bg-black {
|
||||
background-color: #262626;
|
||||
}
|
||||
#lightbox .modal-content {
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -149,7 +211,7 @@
|
|||
import VueCropper from 'vue-cropperjs';
|
||||
import 'cropperjs/dist/cropper.css';
|
||||
export default {
|
||||
components: {
|
||||
components: {
|
||||
VueCropper,
|
||||
VueTimeago
|
||||
},
|
||||
|
@ -182,12 +244,15 @@
|
|||
zoom: null
|
||||
},
|
||||
mediaUrl: null,
|
||||
mediaId: null,
|
||||
stories: [],
|
||||
lightboxMedia: false,
|
||||
duration: 3
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
$('body').addClass('bg-black');
|
||||
this.mediaWatcher();
|
||||
axios.get('/api/stories/v0/fetch/' + this.profileId)
|
||||
.then(res => {
|
||||
|
@ -241,19 +306,22 @@
|
|||
}
|
||||
};
|
||||
|
||||
io.value = null;
|
||||
axios.post('/api/stories/v0/add', form, xhrConfig)
|
||||
.then(function(e) {
|
||||
self.uploadProgress = 100;
|
||||
self.uploading = false;
|
||||
window.location.href = '/i/my/story';
|
||||
self.mediaUrl = e.data.media_url;
|
||||
self.mediaId = e.data.media_id;
|
||||
self.page = e.data.media_type === 'video' ? 'preview' : 'crop';
|
||||
// window.location.href = '/i/my/story';
|
||||
}).catch(function(e) {
|
||||
self.uploading = false;
|
||||
io.value = null;
|
||||
let msg = e.response.data.message ? e.response.data.message : 'Something went wrong.'
|
||||
swal('Oops!', msg, 'warning');
|
||||
self.page = 'error';
|
||||
});
|
||||
io.value = null;
|
||||
self.uploadProgress = 0;
|
||||
});
|
||||
},
|
||||
|
@ -286,8 +354,50 @@
|
|||
window.location.href = '/i/stories/new';
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
navigateTo(path = '/') {
|
||||
window.location.href = path;
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.page = 'landing';
|
||||
},
|
||||
|
||||
performCrop() {
|
||||
this.page = 'cropping';
|
||||
let data = this.$refs.croppa.getData();
|
||||
axios.post('/api/stories/v0/crop', {
|
||||
media_id: this.mediaId,
|
||||
width: data.width,
|
||||
height: data.height,
|
||||
x: data.x,
|
||||
y: data.y
|
||||
}).then(res => {
|
||||
this.page = 'preview';
|
||||
});
|
||||
},
|
||||
|
||||
deleteCurrentStory() {
|
||||
let story = {
|
||||
id: this.mediaId
|
||||
};
|
||||
this.deleteStory(story);
|
||||
this.page = 'landing';
|
||||
},
|
||||
|
||||
shareStoryToFollowers() {
|
||||
axios.post('/api/stories/v0/publish', {
|
||||
media_id: this.mediaId,
|
||||
duration: this.duration
|
||||
}).then(res => {
|
||||
window.location.href = '/i/my/story?id=' + this.mediaId;
|
||||
})
|
||||
},
|
||||
|
||||
viewMyStory() {
|
||||
window.location.href = '/i/my/story';
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -230,6 +230,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
|
|||
Route::delete('v0/delete/{id}', 'StoryController@apiV1Delete')->middleware('throttle:maxStoryDeletePerDay,1440');
|
||||
Route::get('v0/me', 'StoryController@apiV1Me');
|
||||
Route::get('v0/item/{id}', 'StoryController@apiV1Item');
|
||||
Route::post('v0/crop', 'StoryController@cropPhoto');
|
||||
Route::post('v0/publish', 'StoryController@publishStory');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue