kopia lustrzana https://github.com/pixelfed/pixelfed
Merge branch 'frontend-ui-refactor' into feat/double-tap-to-like
commit
7ceaa25205
20
.env.example
20
.env.example
|
@ -1,11 +1,11 @@
|
|||
APP_NAME="PixelFed Test"
|
||||
APP_ENV=local
|
||||
APP_NAME="PixelFed Prod"
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_DEBUG=false
|
||||
|
||||
ADMIN_DOMAIN="localhost"
|
||||
APP_URL=http://localhost
|
||||
APP_DOMAIN="localhost"
|
||||
ADMIN_DOMAIN="localhost"
|
||||
SESSION_DOMAIN="localhost"
|
||||
SESSION_SECURE_COOKIE=true
|
||||
TRUST_PROXIES="*"
|
||||
|
@ -38,22 +38,14 @@ MAIL_ENCRYPTION=null
|
|||
MAIL_FROM_ADDRESS="pixelfed@example.com"
|
||||
MAIL_FROM_NAME="Pixelfed"
|
||||
|
||||
API_BASE="/api/1/"
|
||||
API_SEARCH="/api/search"
|
||||
|
||||
OPEN_REGISTRATION=true
|
||||
ENFORCE_EMAIL_VERIFICATION=true
|
||||
PF_MAX_USERS=1000
|
||||
|
||||
MAX_PHOTO_SIZE=15000
|
||||
MAX_CAPTION_LENGTH=150
|
||||
MAX_ALBUM_LENGTH=4
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
MIX_APP_URL="${APP_URL}"
|
||||
MIX_API_BASE="${API_BASE}"
|
||||
MIX_API_SEARCH="${API_SEARCH}"
|
||||
|
||||
ACTIVITY_PUB=false
|
||||
REMOTE_FOLLOW=false
|
||||
ACTIVITYPUB_INBOX=false
|
||||
|
|
38
.env.testing
38
.env.testing
|
@ -2,10 +2,13 @@ APP_NAME="PixelFed Test"
|
|||
APP_ENV=local
|
||||
APP_KEY=base64:lwX95GbNWX3XsucdMe0XwtOKECta3h/B+p9NbH2jd0E=
|
||||
APP_DEBUG=true
|
||||
APP_URL=https://pixelfed.dev
|
||||
|
||||
ADMIN_DOMAIN="pixelfed.dev"
|
||||
APP_URL=https://pixelfed.dev
|
||||
APP_DOMAIN="pixelfed.dev"
|
||||
ADMIN_DOMAIN="pixelfed.dev"
|
||||
SESSION_DOMAIN="pixelfed.dev"
|
||||
SESSION_SECURE_COOKIE=true
|
||||
TRUST_PROXIES="*"
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
|
||||
|
@ -35,28 +38,29 @@ MAIL_ENCRYPTION=null
|
|||
MAIL_FROM_ADDRESS="pixelfed@example.com"
|
||||
MAIL_FROM_NAME="Pixelfed"
|
||||
|
||||
SESSION_DOMAIN="${APP_DOMAIN}"
|
||||
SESSION_SECURE_COOKIE=true
|
||||
API_BASE="/api/1/"
|
||||
API_SEARCH="/api/search"
|
||||
|
||||
OPEN_REGISTRATION=false
|
||||
ENFORCE_EMAIL_VERIFICATION=true
|
||||
OPEN_REGISTRATION=true
|
||||
ENFORCE_EMAIL_VERIFICATION=false
|
||||
PF_MAX_USERS=1000
|
||||
|
||||
MAX_PHOTO_SIZE=15000
|
||||
MAX_CAPTION_LENGTH=150
|
||||
MAX_ALBUM_LENGTH=4
|
||||
|
||||
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
MIX_APP_URL="${APP_URL}"
|
||||
MIX_API_BASE="${API_BASE}"
|
||||
MIX_API_SEARCH="${API_SEARCH}"
|
||||
|
||||
TELESCOPE_ENABLED=false
|
||||
PF_MAX_USERS=1000
|
||||
ACTIVITY_PUB=false
|
||||
REMOTE_FOLLOW=false
|
||||
ACTIVITYPUB_INBOX=false
|
||||
ACTIVITYPUB_SHAREDINBOX=false
|
||||
# Set these "true" to enable federation.
|
||||
# You might need to also run:
|
||||
# php artisan cache:clear
|
||||
# php artisan optimize:clear
|
||||
# php artisan optimize
|
||||
|
||||
PF_COSTAR_ENABLED=true
|
||||
CS_BLOCKED_DOMAINS='example.org,example.net,example.com'
|
||||
CS_CW_DOMAINS='example.org,example.net,example.com'
|
||||
CS_UNLISTED_DOMAINS='example.org,example.net,example.com'
|
||||
|
||||
## Optional
|
||||
#HORIZON_DARKMODE=false # Horizon theme darkmode
|
||||
#HORIZON_EMBED=false # Single Docker Container mode
|
||||
|
|
|
@ -24,7 +24,8 @@ trait LabsSettings {
|
|||
$this->validate($request, [
|
||||
'profile_layout' => 'nullable',
|
||||
'dark_mode' => 'nullable',
|
||||
'profile_suggestions' => 'nullable'
|
||||
'profile_suggestions' => 'nullable',
|
||||
'moment_bg' => 'nullable'
|
||||
]);
|
||||
|
||||
$changes = false;
|
||||
|
@ -60,6 +61,12 @@ trait LabsSettings {
|
|||
SuggestionService::del($profile->id);
|
||||
}
|
||||
|
||||
if($request->has('moment_bg') && $profile->profile_layout == 'moment') {
|
||||
$bg = in_array($request->input('moment_bg'), $this->momentBackgrounds()) ? $request->input('moment_bg') : 'default';
|
||||
$profile->header_bg = $bg;
|
||||
$changes = true;
|
||||
}
|
||||
|
||||
if($changes == true) {
|
||||
$profile->save();
|
||||
}
|
||||
|
@ -69,4 +76,21 @@ trait LabsSettings {
|
|||
->cookie($cookie);
|
||||
}
|
||||
|
||||
protected function momentBackgrounds()
|
||||
{
|
||||
return [
|
||||
'default',
|
||||
'azure',
|
||||
'passion',
|
||||
'reef',
|
||||
'lush',
|
||||
'neon',
|
||||
'flare',
|
||||
'morning',
|
||||
'tranquil',
|
||||
'mauve',
|
||||
'argon',
|
||||
'royal'
|
||||
];
|
||||
}
|
||||
}
|
|
@ -69,19 +69,13 @@ class LikePipeline implements ShouldQueue
|
|||
$notification->profile_id = $status->profile_id;
|
||||
$notification->actor_id = $actor->id;
|
||||
$notification->action = 'like';
|
||||
$notification->message = $like->toText();
|
||||
$notification->rendered = $like->toHtml();
|
||||
$notification->message = $like->toText($status->in_reply_to_id ? 'comment' : 'post');
|
||||
$notification->rendered = $like->toHtml($status->in_reply_to_id ? 'comment' : 'post');
|
||||
$notification->item_id = $status->id;
|
||||
$notification->item_type = "App\Status";
|
||||
$notification->save();
|
||||
|
||||
Cache::forever('notification.'.$notification->id, $notification);
|
||||
|
||||
$redis = Redis::connection();
|
||||
$key = config('cache.prefix').':user.'.$status->profile_id.'.notifications';
|
||||
$redis->lpush($key, $notification->id);
|
||||
} catch (Exception $e) {
|
||||
Log::error($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
11
app/Like.php
11
app/Like.php
|
@ -27,19 +27,20 @@ class Like extends Model
|
|||
return $this->belongsTo(Status::class);
|
||||
}
|
||||
|
||||
public function toText()
|
||||
public function toText($type = 'post')
|
||||
{
|
||||
$actorName = $this->actor->username;
|
||||
$msg = $type == 'post' ? __('notification.likedPhoto') : __('notification.likedComment');
|
||||
|
||||
return "{$actorName} ".__('notification.likedPhoto');
|
||||
return "{$actorName} ".$msg;
|
||||
}
|
||||
|
||||
public function toHtml()
|
||||
public function toHtml($type = 'post')
|
||||
{
|
||||
$actorName = $this->actor->username;
|
||||
$actorUrl = $this->actor->url();
|
||||
$msg = $type == 'post' ? __('notification.likedPhoto') : __('notification.likedComment');
|
||||
|
||||
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".
|
||||
__('notification.likedPhoto');
|
||||
return "<a href='{$actorUrl}' class='profile-link'>{$actorName}</a> ".$msg;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ class HorizonServiceProvider extends HorizonApplicationServiceProvider
|
|||
// Horizon::routeSmsNotificationsTo('15556667777');
|
||||
// Horizon::routeMailNotificationsTo('example@example.com');
|
||||
// Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
|
||||
|
||||
if(config('horizon.darkmode') == true) {
|
||||
Horizon::night();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -36,15 +40,4 @@ class HorizonServiceProvider extends HorizonApplicationServiceProvider
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
if(config('horizon.darkmode') == true) {
|
||||
Horizon::night();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ class AccountTransformer extends Fractal\TransformerAbstract
|
|||
'avatar_static' => $profile->avatarUrl(),
|
||||
'header' => null,
|
||||
'header_static' => null,
|
||||
'header_bg' => $profile->header_bg,
|
||||
'moved' => null,
|
||||
'fields' => null,
|
||||
'bot' => null,
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"intervention/image": "^2.4",
|
||||
"jenssegers/agent": "^2.6",
|
||||
"laravel/framework": "5.8.*",
|
||||
"laravel/horizon": "^3.0",
|
||||
"laravel/horizon": "^3.1",
|
||||
"laravel/passport": "^7.0",
|
||||
"laravel/tinker": "^1.0",
|
||||
"league/flysystem-aws-s3-v3": "~1.0",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "e7370fab05135d2b5e1161ccfc821f17",
|
||||
"content-hash": "36dce3c2a72bd07cacbd5e9f38e568f4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alchemy/binary-driver",
|
||||
|
@ -71,16 +71,16 @@
|
|||
},
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
"version": "3.93.1",
|
||||
"version": "3.93.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||
"reference": "2dce6e4b7295c6ea44392fc8eff421e3651a8725"
|
||||
"reference": "874c1040edab52df3873157aa54ea51833d48c0e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/2dce6e4b7295c6ea44392fc8eff421e3651a8725",
|
||||
"reference": "2dce6e4b7295c6ea44392fc8eff421e3651a8725",
|
||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/874c1040edab52df3873157aa54ea51833d48c0e",
|
||||
"reference": "874c1040edab52df3873157aa54ea51833d48c0e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -150,7 +150,7 @@
|
|||
"s3",
|
||||
"sdk"
|
||||
],
|
||||
"time": "2019-05-01T18:10:22+00:00"
|
||||
"time": "2019-05-03T18:07:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "beyondcode/laravel-self-diagnosis",
|
||||
|
@ -2262,16 +2262,16 @@
|
|||
},
|
||||
{
|
||||
"name": "league/oauth2-server",
|
||||
"version": "7.3.3",
|
||||
"version": "7.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/oauth2-server.git",
|
||||
"reference": "c7f499849704ebe2c60b45b6d6bb231df5601d4a"
|
||||
"reference": "2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/c7f499849704ebe2c60b45b6d6bb231df5601d4a",
|
||||
"reference": "c7f499849704ebe2c60b45b6d6bb231df5601d4a",
|
||||
"url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf",
|
||||
"reference": "2eb1cf79e59d807d89c256e7ac5e2bf8bdbd4acf",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2335,7 +2335,7 @@
|
|||
"secure",
|
||||
"server"
|
||||
],
|
||||
"time": "2019-03-29T18:19:35+00:00"
|
||||
"time": "2019-05-05T09:22:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mobiledetect/mobiledetectlib",
|
||||
|
@ -2724,16 +2724,16 @@
|
|||
},
|
||||
{
|
||||
"name": "opis/closure",
|
||||
"version": "3.1.6",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/opis/closure.git",
|
||||
"reference": "ccb8e3928c5c8181c76cdd0ed9366c5bcaafd91b"
|
||||
"reference": "09b4389715a7eec100176ea58286649181753508"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/opis/closure/zipball/ccb8e3928c5c8181c76cdd0ed9366c5bcaafd91b",
|
||||
"reference": "ccb8e3928c5c8181c76cdd0ed9366c5bcaafd91b",
|
||||
"url": "https://api.github.com/repos/opis/closure/zipball/09b4389715a7eec100176ea58286649181753508",
|
||||
"reference": "09b4389715a7eec100176ea58286649181753508",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2746,7 +2746,7 @@
|
|||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.1.x-dev"
|
||||
"dev-master": "3.2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
|
@ -2781,7 +2781,7 @@
|
|||
"serialization",
|
||||
"serialize"
|
||||
],
|
||||
"time": "2019-02-22T10:30:00+00:00"
|
||||
"time": "2019-05-05T12:50:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
|
@ -7168,16 +7168,16 @@
|
|||
},
|
||||
{
|
||||
"name": "sebastian/environment",
|
||||
"version": "4.2.1",
|
||||
"version": "4.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/environment.git",
|
||||
"reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a"
|
||||
"reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/3095910f0f0fb155ac4021fc51a4a7a39ac04e8a",
|
||||
"reference": "3095910f0f0fb155ac4021fc51a4a7a39ac04e8a",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
|
||||
"reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -7217,7 +7217,7 @@
|
|||
"environment",
|
||||
"hhvm"
|
||||
],
|
||||
"time": "2019-04-25T07:55:20+00:00"
|
||||
"time": "2019-05-05T09:05:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/exporter",
|
||||
|
|
|
@ -158,6 +158,7 @@ return [
|
|||
App\Providers\AppServiceProvider::class,
|
||||
App\Providers\AuthServiceProvider::class,
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\HorizonServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
|
|
|
@ -2,6 +2,32 @@
|
|||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizon Domain
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the subdomain where Horizon will be accessible from. If this
|
||||
| setting is null, Horizon will reside under the same domain as the
|
||||
| application. Otherwise, this value will serve as the subdomain.
|
||||
|
|
||||
*/
|
||||
|
||||
'domain' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizon Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the URI path where Horizon will be accessible from. Feel free
|
||||
| to change this path to anything you like. Note that the URI will not
|
||||
| affect the paths of its internal API that aren't exposed to users.
|
||||
|
|
||||
*/
|
||||
|
||||
'path' => 'horizon',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizon Redis Connection
|
||||
|
@ -28,6 +54,19 @@ return [
|
|||
|
||||
'prefix' => env('HORIZON_PREFIX', 'horizon-'.str_random(8).':'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Horizon Route Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These middleware will get attached onto each Horizon route, giving you
|
||||
| the chance to add your own middleware to this list or change any of
|
||||
| the existing middleware. Or, you can simply stick with this list.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware' => ['web'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Wait Time Thresholds
|
||||
|
@ -61,6 +100,34 @@ return [
|
|||
'failed' => 10080,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Fast Termination
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When this option is enabled, Horizon's "terminate" command will not
|
||||
| wait on all of the workers to terminate unless the --wait option
|
||||
| is provided. Fast termination can shorten deployment delay by
|
||||
| allowing a new instance of Horizon to start while the last
|
||||
| instance will continue to terminate each of its workers.
|
||||
|
|
||||
*/
|
||||
|
||||
'fast_termination' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Memory Limit (MB)
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value describes the maximum amount of memory the Horizon worker
|
||||
| may consume before it is terminated and restarted. You should set
|
||||
| this value according to the resources available to your server.
|
||||
|
|
||||
*/
|
||||
|
||||
'memory_limit' => 64,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Queue Worker Configuration
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddHeaderToProfilesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('profiles', function (Blueprint $table) {
|
||||
$table->string('header_bg')->nullable()->after('profile_layout');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('profiles', function (Blueprint $table) {
|
||||
$table->dropColumn('header_bg');
|
||||
});
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"/js/activity.js": "/js/activity.js?id=7915246c3bc2b7e9770e",
|
||||
"/js/app.js": "/js/app.js?id=1f05f00eec0e86f49dd4",
|
||||
"/css/app.css": "/css/app.css?id=b407fd02a5b7526f85b4",
|
||||
"/css/appdark.css": "/css/appdark.css?id=b4a7cf4f8dd06abe699e",
|
||||
"/css/app.css": "/css/app.css?id=3a974ff74b6b5905a73c",
|
||||
"/css/appdark.css": "/css/appdark.css?id=107806a000e2ca675a3c",
|
||||
"/css/landing.css": "/css/landing.css?id=d3610108213e88dc080c",
|
||||
"/js/components.js": "/js/components.js?id=25d082643150ee79150c",
|
||||
"/js/compose.js": "/js/compose.js?id=4d8c53b4575f463214f2",
|
||||
"/js/compose.js": "/js/compose.js?id=9ca175b3e11908bd592f",
|
||||
"/js/developers.js": "/js/developers.js?id=1359f11c7349301903f8",
|
||||
"/js/discover.js": "/js/discover.js?id=75fb12b06ee23fa05186",
|
||||
"/js/profile.js": "/js/profile.js?id=b267c34e3f9168a8b307",
|
||||
"/js/profile.js": "/js/profile.js?id=6386a007bdb1796dcc80",
|
||||
"/js/search.js": "/js/search.js?id=0d3d080dc05f4f49b204",
|
||||
"/js/status.js": "/js/status.js?id=bf48fe9060a74d1180f2",
|
||||
"/js/timeline.js": "/js/timeline.js?id=ded47e282e9b3339c1fd"
|
||||
"/js/status.js": "/js/status.js?id=a95243f92346f1724a35",
|
||||
"/js/timeline.js": "/js/timeline.js?id=265d634706cec1b2653d"
|
||||
}
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="ids.length > 0 && ids.length != config.uploader.album_limit" class="card-header py-2 bg-primary m-2 rounded cursor-pointer" v-on:click="addMedia()">
|
||||
<div v-if="ids.length > 0 && ids.length != config.uploader.album_limit" class="card-header py-2 bg-primary m-2 rounded cursor-pointer" v-on:click="addMedia($event)">
|
||||
<p class="text-center mb-0 font-weight-bold text-white"><i class="fas fa-plus mr-1"></i> Add Photo</p>
|
||||
</div>
|
||||
<div v-if="ids.length == 0" class="w-100 h-100 bg-light py-5 cursor-pointer" style="border-bottom: 1px solid #f1f1f1" v-on:click="addMedia()">
|
||||
<div v-if="ids.length == 0" class="w-100 h-100 bg-light py-5 cursor-pointer" style="border-bottom: 1px solid #f1f1f1" v-on:click="addMedia($event)">
|
||||
<p class="text-center mb-0 font-weight-bold p-5">Click here to add photos</p>
|
||||
</div>
|
||||
<div v-if="ids.length > 0">
|
||||
|
@ -316,7 +316,7 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
addMedia() {
|
||||
addMedia(event) {
|
||||
let el = $(event.target);
|
||||
el.attr('disabled', '');
|
||||
let fi = $('.file-input[name="media"]');
|
||||
|
|
|
@ -67,7 +67,8 @@
|
|||
data() {
|
||||
return {
|
||||
notifications: {},
|
||||
notificationCursor: 2
|
||||
notificationCursor: 2,
|
||||
notificationMaxId: 0,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -91,9 +92,12 @@
|
|||
}
|
||||
return true;
|
||||
});
|
||||
let ids = res.data.map(n => n.id);
|
||||
this.notificationMaxId = Math.max(...ids);
|
||||
this.notifications = data;
|
||||
$('.notification-card .loader').addClass('d-none');
|
||||
$('.notification-card .contents').removeClass('d-none');
|
||||
this.notificationPoll();
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -161,6 +165,32 @@
|
|||
let username = status.account.username;
|
||||
let id = status.id;
|
||||
return '/p/' + username + '/' + id;
|
||||
},
|
||||
|
||||
notificationPoll() {
|
||||
let interval = this.notifications.length > 5 ? 15000 : 120000;
|
||||
let self = this;
|
||||
setInterval(function() {
|
||||
axios.get('/api/v1/notifications')
|
||||
.then(res => {
|
||||
let data = res.data.filter(n => {
|
||||
if(n.type == 'share' || self.notificationMaxId >= n.id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if(data.length) {
|
||||
let ids = data.map(n => n.id);
|
||||
self.notificationMaxId = Math.max(...ids);
|
||||
|
||||
self.notifications.unshift(...data);
|
||||
let beep = new Audio('/static/beep.mp3');
|
||||
beep.volume = 0.7;
|
||||
beep.play();
|
||||
$('.notification-card .far.fa-bell').addClass('fas text-danger').removeClass('far text-muted');
|
||||
}
|
||||
});
|
||||
}, interval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -893,11 +893,11 @@ export default {
|
|||
let em = event.target.innerText;
|
||||
if(this.replyText.length == 0) {
|
||||
this.reply_to_profile_id = this.status.account.id;
|
||||
this.replyText = '@' + this.status.account.username + ' ' + em;
|
||||
this.replyText = em + ' ';
|
||||
$('textarea[name="comment"]').focus();
|
||||
} else {
|
||||
this.reply_to_profile_id = this.status.account.id;
|
||||
this.replyText += em;
|
||||
this.replyText += em + ' ';
|
||||
$('textarea[name="comment"]').focus();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -294,7 +294,7 @@
|
|||
</div>
|
||||
|
||||
<div v-if="profileLayout == 'moment'">
|
||||
<div class="w-100 h-100 mt-n3 bg-pixelfed" style="width:100%;min-height:274px;">
|
||||
<div :class="momentBackground()" style="width:100%;min-height:274px;">
|
||||
</div>
|
||||
<div class="bg-white border-bottom">
|
||||
<div class="container">
|
||||
|
@ -1045,6 +1045,16 @@ export default {
|
|||
this.profile.following_count--;
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
momentBackground() {
|
||||
let c = 'w-100 h-100 mt-n3 ';
|
||||
if(this.profile.header_bg) {
|
||||
c += this.profile.header_bg == 'default' ? 'bg-pixelfed' : 'bg-moment-' + this.profile.header_bg;
|
||||
} else {
|
||||
c += 'bg-pixelfed';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,125 +8,173 @@
|
|||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-sm-4 status-card card-md-rounded-0" :data-status-id="status.id" v-for="(status, index) in feed" :key="`${index}-${status.id}`">
|
||||
|
||||
<div class="card-header d-inline-flex align-items-center bg-white">
|
||||
<img v-bind:src="status.account.avatar" width="32px" height="32px" style="border-radius: 32px;">
|
||||
<a class="username font-weight-bold pl-2 text-dark" v-bind:href="status.account.url">
|
||||
{{status.account.username}}
|
||||
</a>
|
||||
<div class="text-right" style="flex-grow:1;">
|
||||
<button class="btn btn-link text-dark no-caret dropdown-toggle py-0" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options">
|
||||
<span class="fas fa-ellipsis-v fa-lg text-muted"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item font-weight-bold" :href="status.url">Go to post</a>
|
||||
<!-- <a class="dropdown-item font-weight-bold" href="#">Share</a>
|
||||
<a class="dropdown-item font-weight-bold" href="#">Embed</a> -->
|
||||
<span v-if="statusOwner(status) == false">
|
||||
<a class="dropdown-item font-weight-bold" :href="reportUrl(status)">Report</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="muteProfile(status)">Mute Profile</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="blockProfile(status)">Block Profile</a>
|
||||
</span>
|
||||
<span v-if="statusOwner(status) == true">
|
||||
<a class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
||||
</span>
|
||||
<span v-if="profile.is_admin == true && modes.mod == true">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a v-if="!statusOwner(status)" class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<h6 class="dropdown-header">Mod Tools</h6>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'autocw')">
|
||||
<p class="mb-0" data-toggle="tooltip" data-placement="bottom" title="Adds a CW to every post made by this account.">Enforce CW</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'noautolink')">
|
||||
<p class="mb-0" title="Do not transform mentions, hashtags or urls into HTML.">No Autolinking</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'unlisted')">
|
||||
<p class="mb-0" title="Removes account from public/network timelines.">Unlisted Posts</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'disable')">
|
||||
<p class="mb-0" title="Temporarily disable account until next time user log in.">Disable Account</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'suspend')">
|
||||
<p class="mb-0" title="This prevents any new interactions, without deleting existing data.">Suspend Account</p>
|
||||
</a>
|
||||
|
||||
</span>
|
||||
<div :data-status-id="status.id" v-for="(status, index) in feed" :key="`${index}-${status.id}`">
|
||||
<div v-if="index == 2 && showSuggestions == true && suggestions.length" class="card mb-sm-4 status-card card-md-rounded-0">
|
||||
<div class="card-header d-flex align-items-center justify-content-between bg-white border-0 pb-0">
|
||||
<h6 class="text-muted font-weight-bold mb-0">Suggestions For You</h6>
|
||||
<span class="cursor-pointer text-muted" v-on:click="hideSuggestions"><i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<div class="card-body row mx-0">
|
||||
<div class="col-12 col-md-4 mb-3" v-for="(rec, index) in suggestions">
|
||||
<div class="card">
|
||||
<div class="card-body text-center pt-3">
|
||||
<p class="mb-0">
|
||||
<a :href="'/'+rec.username">
|
||||
<img :src="rec.avatar" class="img-fluid rounded-circle cursor-pointer" width="45px" height="45px">
|
||||
</a>
|
||||
</p>
|
||||
<div class="py-3">
|
||||
<p class="font-weight-bold text-dark cursor-pointer mb-0">
|
||||
<a :href="'/'+rec.username" class="text-decoration-none text-dark">
|
||||
{{rec.username}}
|
||||
</a>
|
||||
</p>
|
||||
<p class="small text-muted mb-0">{{rec.message}}</p>
|
||||
</div>
|
||||
<p class="mb-0">
|
||||
<a class="btn btn-primary btn-block font-weight-bold py-0" href="#" @click.prevent="expRecFollow(rec.id, index)">Follow</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mb-sm-4 status-card card-md-rounded-0">
|
||||
<div class="card-header d-inline-flex align-items-center bg-white">
|
||||
<img v-bind:src="status.account.avatar" width="32px" height="32px" style="border-radius: 32px;">
|
||||
<a class="username font-weight-bold pl-2 text-dark" v-bind:href="status.account.url">
|
||||
{{status.account.username}}
|
||||
</a>
|
||||
<div class="text-right" style="flex-grow:1;">
|
||||
<button class="btn btn-link text-dark no-caret dropdown-toggle py-0" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Post options">
|
||||
<span class="fas fa-ellipsis-v fa-lg text-muted"></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a class="dropdown-item font-weight-bold" :href="status.url">Go to post</a>
|
||||
<!-- <a class="dropdown-item font-weight-bold" href="#">Share</a>
|
||||
<a class="dropdown-item font-weight-bold" href="#">Embed</a> -->
|
||||
<span v-if="statusOwner(status) == false">
|
||||
<a class="dropdown-item font-weight-bold" :href="reportUrl(status)">Report</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="muteProfile(status)">Mute Profile</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="blockProfile(status)">Block Profile</a>
|
||||
</span>
|
||||
<span v-if="statusOwner(status) == true">
|
||||
<a class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
||||
</span>
|
||||
<span v-if="profile.is_admin == true && modes.mod == true">
|
||||
<div class="dropdown-divider"></div>
|
||||
<a v-if="!statusOwner(status)" class="dropdown-item font-weight-bold text-danger" v-on:click="deletePost(status)">Delete</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<h6 class="dropdown-header">Mod Tools</h6>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'autocw')">
|
||||
<p class="mb-0" data-toggle="tooltip" data-placement="bottom" title="Adds a CW to every post made by this account.">Enforce CW</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'noautolink')">
|
||||
<p class="mb-0" title="Do not transform mentions, hashtags or urls into HTML.">No Autolinking</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'unlisted')">
|
||||
<p class="mb-0" title="Removes account from public/network timelines.">Unlisted Posts</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'disable')">
|
||||
<p class="mb-0" title="Temporarily disable account until next time user log in.">Disable Account</p>
|
||||
</a>
|
||||
<a class="dropdown-item font-weight-bold" v-on:click="moderatePost(status, 'suspend')">
|
||||
<p class="mb-0" title="This prevents any new interactions, without deleting existing data.">Suspend Account</p>
|
||||
</a>
|
||||
|
||||
<div class="postPresenterContainer" v-on:doubletap="likeStatus(status, $event)">
|
||||
<div v-if="status.pf_type === 'photo'" class="w-100">
|
||||
<photo-presenter :status="status" v-on:lightbox="lightbox"></photo-presenter>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'video'" class="w-100">
|
||||
<video-presenter :status="status"></video-presenter>
|
||||
<div class="postPresenterContainer" v-on:doubletap="likeStatus(status, $event)">
|
||||
<div v-if="status.pf_type === 'photo'" class="w-100">
|
||||
<photo-presenter :status="status" v-on:lightbox="lightbox"></photo-presenter>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'video'" class="w-100">
|
||||
<video-presenter :status="status"></video-presenter>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'photo:album'" class="w-100">
|
||||
<photo-album-presenter :status="status" v-on:lightbox="lightbox"></photo-album-presenter>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'video:album'" class="w-100">
|
||||
<video-album-presenter :status="status"></video-album-presenter>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'photo:video:album'" class="w-100">
|
||||
<mixed-album-presenter :status="status" v-on:lightbox="lightbox"></mixed-album-presenter>
|
||||
</div>
|
||||
|
||||
<div v-else class="w-100">
|
||||
<p class="text-center p-0 font-weight-bold text-white">Error: Problem rendering preview.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'photo:album'" class="w-100">
|
||||
<photo-album-presenter :status="status" v-on:lightbox="lightbox"></photo-album-presenter>
|
||||
<div class="card-body">
|
||||
<div class="reactions my-1">
|
||||
<h3 v-bind:class="[status.favourited ? 'fas fa-heart text-danger pr-3 m-0 cursor-pointer' : 'far fa-heart pr-3 m-0 like-btn cursor-pointer']" title="Like" v-on:click="likeStatus(status, $event)"></h3>
|
||||
<h3 v-if="!status.comments_disabled" class="far fa-comment pr-3 m-0 cursor-pointer" title="Comment" v-on:click="commentFocus(status, $event)"></h3>
|
||||
<h3 v-bind:class="[status.reblogged ? 'far fa-share-square pr-3 m-0 text-primary cursor-pointer' : 'far fa-share-square pr-3 m-0 share-btn cursor-pointer']" title="Share" v-on:click="shareStatus(status, $event)"></h3>
|
||||
</div>
|
||||
|
||||
<div class="likes font-weight-bold" v-if="expLc(status) == true">
|
||||
<span class="like-count">{{status.favourites_count}}</span> {{status.favourites_count == 1 ? 'like' : 'likes'}}
|
||||
</div>
|
||||
<div class="caption">
|
||||
<p class="mb-2 read-more" style="overflow: hidden;">
|
||||
<span class="username font-weight-bold">
|
||||
<bdi><a class="text-dark" :href="status.account.url">{{status.account.username}}</a></bdi>
|
||||
</span>
|
||||
<span v-html="status.content"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="comments" v-if="status.id == replyId && !status.comments_disabled">
|
||||
<p class="mb-0 d-flex justify-content-between align-items-top read-more" style="overflow-y: hidden;" v-for="(reply, index) in replies">
|
||||
<span>
|
||||
<a class="text-dark font-weight-bold mr-1" :href="reply.account.url">{{reply.account.username}}</a>
|
||||
<span v-html="reply.content"></span>
|
||||
</span>
|
||||
<span class="mb-0" style="min-width:38px">
|
||||
<span v-on:click="likeStatus(reply, $event)"><i v-bind:class="[reply.favourited ? 'fas fa-heart fa-sm text-danger':'far fa-heart fa-sm text-lighter']"></i></span>
|
||||
<post-menu :status="reply" :profile="profile" size="sm" :modal="'true'" :feed="feed" class="d-inline-flex pl-2"></post-menu>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="timestamp mt-2">
|
||||
<p class="small text-uppercase mb-0">
|
||||
<a :href="status.url" class="text-muted">
|
||||
<timeago :datetime="status.created_at" :auto-update="60" :converter-options="{includeSeconds:true}" :title="timestampFormat(status.created_at)" v-b-tooltip.hover.bottom></timeago>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'video:album'" class="w-100">
|
||||
<video-album-presenter :status="status"></video-album-presenter>
|
||||
<div v-if="status.id == replyId && !status.comments_disabled" class="card-footer bg-white px-2 py-0">
|
||||
<ul class="nav align-items-center emoji-reactions" style="overflow-x: scroll;flex-wrap: unset;">
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😂</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">💯</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">❤️</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">🙌</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">👏</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😍</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😯</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😢</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😅</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😁</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">🙂</li>
|
||||
<li class="nav-item" v-on:click="emojiReaction(status)">😎</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div v-else-if="status.pf_type === 'photo:video:album'" class="w-100">
|
||||
<mixed-album-presenter :status="status" v-on:lightbox="lightbox"></mixed-album-presenter>
|
||||
<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)"/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div v-else class="w-100">
|
||||
<p class="text-center p-0 font-weight-bold text-white">Error: Problem rendering preview.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
<div class="reactions my-1">
|
||||
<h3 v-bind:class="[status.favourited ? 'fas fa-heart text-danger pr-3 m-0 cursor-pointer' : 'far fa-heart pr-3 m-0 like-btn cursor-pointer']" title="Like" v-on:click="likeStatus(status, $event)"></h3>
|
||||
<h3 v-if="!status.comments_disabled" class="far fa-comment pr-3 m-0 cursor-pointer" title="Comment" v-on:click="commentFocus(status, $event)"></h3>
|
||||
<h3 v-bind:class="[status.reblogged ? 'far fa-share-square pr-3 m-0 text-primary cursor-pointer' : 'far fa-share-square pr-3 m-0 share-btn cursor-pointer']" title="Share" v-on:click="shareStatus(status, $event)"></h3>
|
||||
</div>
|
||||
|
||||
<div class="likes font-weight-bold" v-if="expLc(status) == true">
|
||||
<span class="like-count">{{status.favourites_count}}</span> {{status.favourites_count == 1 ? 'like' : 'likes'}}
|
||||
</div>
|
||||
<div class="caption">
|
||||
<p class="mb-2 read-more" style="overflow: hidden;">
|
||||
<span class="username font-weight-bold">
|
||||
<bdi><a class="text-dark" :href="status.account.url">{{status.account.username}}</a></bdi>
|
||||
</span>
|
||||
<span v-html="status.content"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="comments" v-if="status.id == replyId && !status.comments_disabled">
|
||||
<p class="mb-0 d-flex justify-content-between align-items-top read-more" style="overflow-y: hidden;" v-for="(reply, index) in replies">
|
||||
<span>
|
||||
<a class="text-dark font-weight-bold mr-1" :href="reply.account.url">{{reply.account.username}}</a>
|
||||
<span v-html="reply.content"></span>
|
||||
</span>
|
||||
<span class="mb-0" style="min-width:38px">
|
||||
<span v-on:click="likeStatus(reply, $event)"><i v-bind:class="[reply.favourited ? 'fas fa-heart fa-sm text-danger':'far fa-heart fa-sm text-lighter']"></i></span>
|
||||
<post-menu :status="reply" :profile="profile" size="sm" :modal="'true'" :feed="feed" class="d-inline-flex pl-2"></post-menu>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="timestamp mt-2">
|
||||
<p class="small text-uppercase mb-0">
|
||||
<a :href="status.url" class="text-muted">
|
||||
<timeago :datetime="status.created_at" :auto-update="60" :converter-options="{includeSeconds:true}" :title="timestampFormat(status.created_at)" v-b-tooltip.hover.bottom></timeago>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-footer bg-white" v-if="status.id == replyId">
|
||||
<form class="" v-on:submit.prevent="commentSubmit(status, $event)">
|
||||
<input type="hidden" name="item" value="">
|
||||
<input class="form-control status-reply-input" name="comment" placeholder="Add a comment…" autocomplete="off">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="modes.infinite == true && !loading && feed.length > 0">
|
||||
|
@ -220,10 +268,12 @@
|
|||
<notification-card></notification-card>
|
||||
</div>
|
||||
|
||||
<div v-show="suggestions.length && config.ab && config.ab.rec == true" class="mb-4">
|
||||
<div v-show="showSuggestions == true && suggestions.length && config.ab && config.ab.rec == true" class="mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header bg-white text-center">
|
||||
<div class="card-header bg-white d-flex align-items-center justify-content-between">
|
||||
<div></div>
|
||||
<div class="small text-dark text-uppercase font-weight-bold">Suggestions</div>
|
||||
<div class="small text-muted cursor-pointer" v-on:click="hideSuggestions"><i class="fas fa-times"></i></div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<div v-for="(rec, index) in suggestions" class="media align-items-center mt-3">
|
||||
|
@ -355,6 +405,24 @@
|
|||
.small .custom-control-label {
|
||||
padding-top: 3px;
|
||||
}
|
||||
.reply-btn {
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
right: 20px;
|
||||
width: 60px;
|
||||
text-align: center;
|
||||
border-radius: 0 3px 3px 0;
|
||||
}
|
||||
.emoji-reactions .nav-item {
|
||||
font-size: 1.2rem;
|
||||
padding: 9px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.emoji-reactions::-webkit-scrollbar {
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
background: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -386,7 +454,11 @@
|
|||
following: [],
|
||||
followingCursor: 1,
|
||||
followingMore: true,
|
||||
lightboxMedia: false
|
||||
lightboxMedia: false,
|
||||
showSuggestions: false,
|
||||
showReadMore: true,
|
||||
replyStatus: {},
|
||||
replyText: '',
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -406,13 +478,27 @@
|
|||
this.modes.dark = true;
|
||||
}
|
||||
|
||||
if(localStorage.getItem('pf_metro_ui.exp.rec') == 'false') {
|
||||
this.showSuggestions = false;
|
||||
} else {
|
||||
this.showSuggestions = true;
|
||||
}
|
||||
|
||||
if(localStorage.getItem('pf_metro_ui.exp.rm') == 'false') {
|
||||
this.showReadMore = false;
|
||||
} else {
|
||||
this.showReadMore = true;
|
||||
}
|
||||
|
||||
this.$nextTick(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
},
|
||||
|
||||
updated() {
|
||||
pixelfed.readmore();
|
||||
if(this.showReadMore == true) {
|
||||
pixelfed.readmore();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
@ -462,9 +548,7 @@
|
|||
this.max_id = Math.min(...ids);
|
||||
$('.timeline .pagination').removeClass('d-none');
|
||||
this.loading = false;
|
||||
if(window.outerWidth > 767) {
|
||||
this.expRec();
|
||||
}
|
||||
this.expRec();
|
||||
}).catch(err => {
|
||||
});
|
||||
},
|
||||
|
@ -545,7 +629,10 @@
|
|||
return;
|
||||
}
|
||||
this.replies = {};
|
||||
this.replyStatus = {};
|
||||
this.replyText = '';
|
||||
this.replyId = status.id;
|
||||
this.replyStatus = status;
|
||||
this.fetchStatusComments(status, '');
|
||||
},
|
||||
|
||||
|
@ -677,16 +764,12 @@
|
|||
|
||||
commentSubmit(status, $event) {
|
||||
let id = status.id;
|
||||
let form = $event.target;
|
||||
let input = $(form).find('input[name="comment"]');
|
||||
let comment = input.val();
|
||||
let comments = form.parentElement.parentElement.getElementsByClassName('comments')[0];
|
||||
let comment = this.replyText;
|
||||
axios.post('/i/comment', {
|
||||
item: id,
|
||||
comment: comment
|
||||
}).then(res => {
|
||||
form.reset();
|
||||
form.blur();
|
||||
this.replyText = '';
|
||||
this.replies.push(res.data.entity);
|
||||
});
|
||||
},
|
||||
|
@ -1006,7 +1089,23 @@
|
|||
|
||||
ownerOrAdmin(status) {
|
||||
return this.owner(status) || this.admin();
|
||||
}
|
||||
},
|
||||
|
||||
hideSuggestions() {
|
||||
localStorage.setItem('pf_metro_ui.exp.rec', false);
|
||||
this.showSuggestions = false;
|
||||
},
|
||||
|
||||
emojiReaction(status) {
|
||||
let em = event.target.innerText;
|
||||
if(this.replyText.length == 0) {
|
||||
this.replyText = em + ' ';
|
||||
$('textarea[name="comment"]').focus();
|
||||
} else {
|
||||
this.replyText += em + ' ';
|
||||
$('textarea[name="comment"]').focus();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -24,3 +24,5 @@
|
|||
@import '~plyr/dist/plyr.css';
|
||||
|
||||
@import '~vue-loading-overlay/dist/vue-loading.css';
|
||||
|
||||
@import "moment";
|
||||
|
|
|
@ -66,3 +66,5 @@ textarea {
|
|||
@import '~plyr/dist/plyr.css';
|
||||
|
||||
@import '~vue-loading-overlay/dist/vue-loading.css';
|
||||
|
||||
@import "moment";
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
red
|
||||
*/
|
||||
.bg-moment-passion {
|
||||
background: #e53935;
|
||||
background: -webkit-linear-gradient(to left, #e35d5b, #e53935);
|
||||
background: linear-gradient(to left, #e35d5b, #e53935);
|
||||
}
|
||||
|
||||
/*
|
||||
teal/purple
|
||||
*/
|
||||
.bg-moment-azure {
|
||||
background: #7F7FD5;
|
||||
background: -webkit-linear-gradient(to left, #91EAE4, #86A8E7, #7F7FD5);
|
||||
background: linear-gradient(to left, #91EAE4, #86A8E7, #7F7FD5);
|
||||
}
|
||||
|
||||
/*
|
||||
blue
|
||||
*/
|
||||
.bg-moment-reef {
|
||||
background: #00d2ff;
|
||||
background: -webkit-linear-gradient(to right, #3a7bd5, #00d2ff);
|
||||
background: linear-gradient(to right, #3a7bd5, #00d2ff);
|
||||
}
|
||||
|
||||
/*
|
||||
lush green
|
||||
*/
|
||||
.bg-moment-lush {
|
||||
background: #56ab2f;
|
||||
background: -webkit-linear-gradient(to left, #a8e063, #56ab2f);
|
||||
background: linear-gradient(to left, #a8e063, #56ab2f);
|
||||
}
|
||||
|
||||
/*
|
||||
neon green
|
||||
*/
|
||||
.bg-moment-neon {
|
||||
background: #B3FFAB;
|
||||
background: -webkit-linear-gradient(to right, #12FFF7, #B3FFAB);
|
||||
background: linear-gradient(to right, #12FFF7, #B3FFAB);
|
||||
}
|
||||
|
||||
/*
|
||||
orange
|
||||
*/
|
||||
.bg-moment-flare {
|
||||
background: #f12711;
|
||||
background: -webkit-linear-gradient(to left, #f5af19, #f12711);
|
||||
background: linear-gradient(to left, #f5af19, #f12711);
|
||||
}
|
||||
|
||||
/*
|
||||
orange/pink
|
||||
*/
|
||||
.bg-moment-morning {
|
||||
background: #FF5F6D;
|
||||
background: -webkit-linear-gradient(to left, #FFC371, #FF5F6D);
|
||||
background: linear-gradient(to left, #FFC371, #FF5F6D);
|
||||
}
|
||||
|
||||
/*
|
||||
pink
|
||||
*/
|
||||
.bg-moment-tranquil {
|
||||
background: #EECDA3;
|
||||
background: -webkit-linear-gradient(to right, #EF629F, #EECDA3);
|
||||
background: linear-gradient(to right, #EF629F, #EECDA3);
|
||||
}
|
||||
|
||||
/*
|
||||
purple
|
||||
*/
|
||||
.bg-moment-mauve {
|
||||
background: #42275a;
|
||||
background: -webkit-linear-gradient(to left, #734b6d, #42275a);
|
||||
background: linear-gradient(to left, #734b6d, #42275a);
|
||||
}
|
||||
|
||||
/*
|
||||
purple
|
||||
*/
|
||||
.bg-moment-argon {
|
||||
background: #03001e;
|
||||
background: -webkit-linear-gradient(to left, #fdeff9, #ec38bc, #7303c0, #03001e);
|
||||
background: linear-gradient(to left, #fdeff9, #ec38bc, #7303c0, #03001e);
|
||||
}
|
||||
|
||||
/*
|
||||
dark blue
|
||||
*/
|
||||
.bg-moment-royal {
|
||||
background: #141E30;
|
||||
background: -webkit-linear-gradient(to left, #243B55, #141E30);
|
||||
background: linear-gradient(to left, #243B55, #141E30);
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
return [
|
||||
|
||||
'likedPhoto' => 'liked your photo.',
|
||||
'likedPhoto' => 'liked your post.',
|
||||
'likedComment' => 'liked your comment.',
|
||||
'startedFollowingYou' => 'started following you.',
|
||||
'commented' => 'commented on your post.',
|
||||
'mentionedYou' => 'mentioned you.',
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="row justify-content-center">
|
||||
<div class="col-lg-5">
|
||||
<div class="card">
|
||||
<div class="card-header">{{ __('Reset Password') }}</div>
|
||||
<div class="card-header bg-white p-3 text-center font-weight-bold">{{ __('Reset Password') }}</div>
|
||||
|
||||
<div class="card-body">
|
||||
<form method="POST" action="{{ route('password.request') }}">
|
||||
|
@ -14,11 +14,8 @@
|
|||
<input type="hidden" name="token" value="{{ $token }}">
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" required autofocus>
|
||||
|
||||
<div class="col-md-12">
|
||||
<input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ $email ?? old('email') }}" placeholder="{{ __('E-Mail Address') }}" required autofocus>
|
||||
@if ($errors->has('email'))
|
||||
<span class="invalid-feedback">
|
||||
<strong>{{ $errors->first('email') }}</strong>
|
||||
|
@ -26,12 +23,10 @@
|
|||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>
|
||||
<div class="col-md-12">
|
||||
<input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" placeholder="{{ __('Password') }}" required>
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<span class="invalid-feedback">
|
||||
|
@ -42,10 +37,8 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>
|
||||
|
||||
<div class="col-md-6">
|
||||
<input id="password-confirm" type="password" class="form-control{{ $errors->has('password_confirmation') ? ' is-invalid' : '' }}" name="password_confirmation" required>
|
||||
<div class="col-md-12">
|
||||
<input id="password-confirm" type="password" class="form-control{{ $errors->has('password_confirmation') ? ' is-invalid' : '' }}" name="password_confirmation" placeholder="{{ __('Confirm Password') }}" required>
|
||||
|
||||
@if ($errors->has('password_confirmation'))
|
||||
<span class="invalid-feedback">
|
||||
|
@ -56,8 +49,8 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group row mb-0">
|
||||
<div class="col-md-6 offset-md-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<div class="col-md-12">
|
||||
<button type="submit" class="btn btn-primary btn-block py-0 font-weight-bold">
|
||||
{{ __('Reset Password') }}
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -31,6 +31,124 @@
|
|||
</label>
|
||||
<p class="text-muted small help-text">MomentUI offers an alternative layout for posts and your profile.</p>
|
||||
</div>
|
||||
@if($profile->profile_layout == 'moment')
|
||||
<div class="form-check pb-3">
|
||||
<label class="form-check-label font-weight-bold mb-3" for="profile_layout">
|
||||
{{__('MomentUI Profile Header Color')}}
|
||||
</label>
|
||||
<div class="row">
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-pixelfed rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Default</p>
|
||||
<input class="form-check-input mx-0 pl-0" type="radio" name="moment_bg" value="default" {{$profile->header_bg == 'default' || !$profile->header_bg ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-azure rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Azure</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="azure" {{$profile->header_bg == 'azure' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-passion rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Passion</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="passion" {{$profile->header_bg == 'passion' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-reef rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Reef</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="reef" {{$profile->header_bg == 'reef' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-lush rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Lush</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="lush" {{$profile->header_bg == 'lush' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-neon rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Neon</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="neon" {{$profile->header_bg == 'neon' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-flare rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Flare</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="flare" {{$profile->header_bg == 'flare' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-morning rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Morning</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="morning" {{$profile->header_bg == 'morning' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-tranquil rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Tranquil</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="tranquil" {{$profile->header_bg == 'tranquil' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-mauve rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Mauve</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="mauve" {{$profile->header_bg == 'mauve' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-argon rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Argon</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="argon" {{$profile->header_bg == 'argon' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6 col-sm-3 pb-5">
|
||||
<div class="">
|
||||
<p class="form-check-label">
|
||||
<div class="bg-moment-royal rounded-circle box-shadow" style="width:60px; height:60px"></div>
|
||||
</p>
|
||||
<p class="mb-0 small text-muted">Royal</p>
|
||||
<input class="form-check-input mx-0" type="radio" name="moment_bg" value="royal" {{$profile->header_bg == 'royal' ? 'checked':''}}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-muted small help-text">Set your MomentUI profile background color. Adding a custom header image will be supported in a future version.</p>
|
||||
</div>
|
||||
@endif
|
||||
<div class="form-check pb-3">
|
||||
<input class="form-check-input" type="checkbox" name="dark_mode" id="dark_mode" {{request()->hasCookie('dark-mode') ? 'checked':''}}>
|
||||
<label class="form-check-label font-weight-bold" for="dark_mode">
|
||||
|
@ -38,6 +156,22 @@
|
|||
</label>
|
||||
<p class="text-muted small help-text">Use dark mode theme.</p>
|
||||
</div>
|
||||
@if(config('exp.rec') == true)
|
||||
<div class="form-check pb-3">
|
||||
<input class="form-check-input" type="checkbox" name="show_suggestions" id="show_suggestions">
|
||||
<label class="form-check-label font-weight-bold" for="show_suggestions">
|
||||
{{__('Profile Suggestions')}}
|
||||
</label>
|
||||
<p class="text-muted small help-text">Show Profile Suggestions.</p>
|
||||
</div>
|
||||
@endif
|
||||
<div class="form-check pb-3">
|
||||
<input class="form-check-input" type="checkbox" name="show_readmore" id="show_readmore">
|
||||
<label class="form-check-label font-weight-bold" for="show_readmore">
|
||||
{{__('Use Read More')}}
|
||||
</label>
|
||||
<p class="text-muted small help-text">Collapses captions/comments more than 3 lines.</p>
|
||||
</div>
|
||||
<div class="py-3">
|
||||
<p class="font-weight-bold text-muted text-center">Discovery</p>
|
||||
<hr>
|
||||
|
@ -58,4 +192,37 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
let showSuggestions = localStorage.getItem('pf_metro_ui.exp.rec') == 'false' ? false : true;
|
||||
let showReadMore = localStorage.getItem('pf_metro_ui.exp.rm') == 'false' ? false : true;
|
||||
|
||||
if(showSuggestions == true) {
|
||||
$('#show_suggestions').attr('checked', true);
|
||||
}
|
||||
|
||||
if(showReadMore == true) {
|
||||
$('#show_readmore').attr('checked', true);
|
||||
}
|
||||
|
||||
$('#show_suggestions').on('change', function(e) {
|
||||
if(e.target.checked) {
|
||||
localStorage.removeItem('pf_metro_ui.exp.rec');
|
||||
} else {
|
||||
localStorage.setItem('pf_metro_ui.exp.rec', false);
|
||||
}
|
||||
});
|
||||
|
||||
$('#show_readmore').on('change', function(e) {
|
||||
if(e.target.checked) {
|
||||
localStorage.removeItem('pf_metro_ui.exp.rm');
|
||||
} else {
|
||||
localStorage.setItem('pf_metro_ui.exp.rm', false);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
Ładowanie…
Reference in New Issue