1
0
Fork 0

Merge branch 'frontend-ui-refactor' into feat/double-tap-to-like

This commit is contained in:
daniel 2019-05-06 20:47:13 -06:00 committed by GitHub
commit 7ceaa25205
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 748 additions and 237 deletions

View File

@ -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

View File

@ -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

View File

@ -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'
];
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}
}

View File

@ -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,

View File

@ -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",

44
composer.lock generated
View File

@ -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",

View File

@ -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,

View File

@ -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

View File

@ -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');
});
}
}

2
public/css/app.css vendored

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

2
public/js/status.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -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"
}

View File

@ -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"]');

View File

@ -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);
}
}
}

View File

@ -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();
}
},

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -24,3 +24,5 @@
@import '~plyr/dist/plyr.css';
@import '~vue-loading-overlay/dist/vue-loading.css';
@import "moment";

View File

@ -66,3 +66,5 @@ textarea {
@import '~plyr/dist/plyr.css';
@import '~vue-loading-overlay/dist/vue-loading.css';
@import "moment";

98
resources/assets/sass/moment.scss vendored Normal file
View File

@ -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);
}

View File

@ -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.',

View File

@ -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>

View File

@ -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