Bläddra i källkod

Add infinite scroll to profiles, and support private profiles

Daniel Supernault 7 år sedan
förälder
incheckning
4ba9e2cd6c

+ 23 - 2
app/Http/Controllers/ProfileController.php

@@ -18,6 +18,7 @@ class ProfileController extends Controller
     public function show(Request $request, $username)
     public function show(Request $request, $username)
     {
     {
       $user = Profile::whereUsername($username)->firstOrFail();
       $user = Profile::whereUsername($username)->firstOrFail();
+      $settings = User::whereUsername($username)->firstOrFail()->settings;
 
 
       $mimes = [
       $mimes = [
         'application/activity+json', 
         'application/activity+json', 
@@ -27,7 +28,12 @@ class ProfileController extends Controller
       if(in_array($request->header('accept'), $mimes) && config('pixelfed.activitypub_enabled')) {
       if(in_array($request->header('accept'), $mimes) && config('pixelfed.activitypub_enabled')) {
         return $this->showActivityPub($request, $user);
         return $this->showActivityPub($request, $user);
       }
       }
-
+      if($user->is_private == true) {
+        $can_access = $this->privateProfileCheck($user);
+        if($can_access !== true) {
+          abort(403);
+        }
+      }
       // TODO: refactor this mess
       // TODO: refactor this mess
       $owner = Auth::check() && Auth::id() === $user->user_id;
       $owner = Auth::check() && Auth::id() === $user->user_id;
       $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
       $is_following = ($owner == false && Auth::check()) ? $user->followedBy(Auth::user()->profile) : false;
@@ -39,7 +45,22 @@ class ProfileController extends Controller
                   ->withCount(['comments', 'likes'])
                   ->withCount(['comments', 'likes'])
                   ->simplePaginate(21);
                   ->simplePaginate(21);
 
 
-      return view('profile.show', compact('user', 'owner', 'is_following', 'is_admin', 'timeline'));
+      return view('profile.show', compact('user', 'settings', 'owner', 'is_following', 'is_admin', 'timeline'));
+    }
+
+    protected function privateProfileCheck(Profile $profile)
+    {
+      if(Auth::check() === false) {
+        return false;
+      }
+
+      $follower_ids = (array) $profile->followers()->pluck('followers.profile_id');
+      $pid = Auth::user()->profile->id;
+      if(!in_array($pid, $follower_ids) && $pid !== $profile->id) {
+        return false;
+      }
+
+      return true;
     }
     }
 
 
     public function showActivityPub(Request $request, $user)
     public function showActivityPub(Request $request, $user)

+ 82 - 5
app/Http/Controllers/SettingsController.php

@@ -3,8 +3,8 @@
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
-use App\{Profile, User};
-use Auth;
+use App\{AccountLog, Profile, User};
+use Auth, DB;
 
 
 class SettingsController extends Controller
 class SettingsController extends Controller
 {
 {
@@ -89,6 +89,34 @@ class SettingsController extends Controller
       return view('settings.avatar');
       return view('settings.avatar');
     }
     }
 
 
+    public function accessibility()
+    {
+      $settings = Auth::user()->settings;
+      return view('settings.accessibility', compact('settings'));
+    }
+
+    public function accessibilityStore(Request $request)
+    {
+      $settings = Auth::user()->settings;
+      $fields = [
+          'compose_media_descriptions',
+          'reduce_motion',
+          'optimize_screen_reader',
+          'high_contrast_mode',
+          'video_autoplay'
+      ];
+      foreach($fields as $field) {
+          $form = $request->input($field);
+          if($form == 'on') {
+             $settings->{$field} = true;
+          } else {
+             $settings->{$field} = false;
+          }
+          $settings->save();
+      }
+      return redirect(route('settings.accessibility'))->with('status', 'Settings successfully updated!');
+    }
+
     public function notifications()
     public function notifications()
     {
     {
       return view('settings.notifications');
       return view('settings.notifications');
@@ -96,12 +124,61 @@ class SettingsController extends Controller
 
 
     public function privacy()
     public function privacy()
     {
     {
-      return view('settings.privacy');
+      $settings = Auth::user()->settings;
+      $is_private = Auth::user()->profile->is_private;
+      $settings['is_private'] = (bool) $is_private;
+      return view('settings.privacy', compact('settings'));
+    }
+
+    public function privacyStore(Request $request)
+    {
+      $settings = Auth::user()->settings;
+      $profile = Auth::user()->profile;
+      $fields = [
+          'is_private',
+          'crawlable',
+      ];
+      foreach($fields as $field) {
+          $form = $request->input($field);
+          if($field == 'is_private') {
+            if($form == 'on') {
+               $profile->{$field} = true;
+               $settings->show_guests = false;
+               $settings->show_discover = false;
+               $profile->save();
+            } else {
+               $profile->{$field} = false;
+               $profile->save();
+            }
+          } elseif($field == 'crawlable') {
+            if($form == 'on') {
+               $settings->{$field} = false;
+            } else {
+               $settings->{$field} = true;
+            }
+          } else {
+            if($form == 'on') {
+               $settings->{$field} = true;
+            } else {
+               $settings->{$field} = false;
+            }
+          }
+          $settings->save();
+      }
+      return redirect(route('settings.privacy'))->with('status', 'Settings successfully updated!');
     }
     }
 
 
     public function security()
     public function security()
     {
     {
-      return view('settings.security');
+      $sessions = DB::table('sessions')
+        ->whereUserId(Auth::id())
+        ->limit(20)
+        ->get();
+      $activity = AccountLog::whereUserId(Auth::id())
+      ->orderBy('created_at','desc')
+      ->limit(50)
+      ->get();
+      return view('settings.security', compact('sessions', 'activity'));
     }
     }
 
 
     public function applications()
     public function applications()
@@ -121,7 +198,7 @@ class SettingsController extends Controller
 
 
     public function dataImportInstagram()
     public function dataImportInstagram()
     {
     {
-      return view('settings.import.ig');
+      return view('settings.import.instagram.home');
     }
     }
 
 
     public function developers()
     public function developers()

+ 57 - 29
resources/views/profile/show.blade.php

@@ -4,7 +4,7 @@
 
 
 @include('profile.partial.user-info')
 @include('profile.partial.user-info')
 
 
-@if($owner == true)
+@if(true === $owner)
 <div>
 <div>
   <ul class="nav nav-topbar d-flex justify-content-center border-0">
   <ul class="nav nav-topbar d-flex justify-content-center border-0">
     <li class="nav-item">
     <li class="nav-item">
@@ -16,51 +16,79 @@
   </ul>
   </ul>
 </div>
 </div>
 @endif
 @endif
-<div class="container">
-  <div class="profile-timeline mt-5 row">
+<div class="container mt-5">
     @if($owner && request()->is('*/saved'))
     @if($owner && request()->is('*/saved'))
     <div class="col-12">
     <div class="col-12">
       <p class="text-muted font-weight-bold small">{{__('profile.savedWarning')}}</p>
       <p class="text-muted font-weight-bold small">{{__('profile.savedWarning')}}</p>
     </div>
     </div>
     @endif
     @endif
+  <div class="profile-timeline">
+    <div class="row">
     @if($timeline->count() > 0)
     @if($timeline->count() > 0)
     @foreach($timeline as $status)
     @foreach($timeline as $status)
-    <div class="col-12 col-md-4 mb-4">
-      <a class="card info-overlay" href="{{$status->url()}}">
-        <div class="square {{$status->firstMedia()->filter_class}}">
-          <div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
-          <div class="info-overlay-text">
-            <h5 class="text-white m-auto font-weight-bold">
-              <span class="pr-4">
-              <span class="far fa-heart fa-lg pr-1"></span> {{$status->likes_count}}
-              </span>
-              <span>
-              <span class="far fa-comment fa-lg pr-1"></span> {{$status->comments_count}}
-              </span>
-            </h5>
+      <div class="col-12 col-md-4 mb-4">
+        <a class="card info-overlay" href="{{$status->url()}}">
+          <div class="square {{$status->firstMedia()->filter_class}}">
+            <div class="square-content" style="background-image: url('{{$status->thumb()}}')"></div>
+            <div class="info-overlay-text">
+              <h5 class="text-white m-auto font-weight-bold">
+                <span class="pr-4">
+                <span class="far fa-heart fa-lg pr-1"></span> {{$status->likes_count}}
+                </span>
+                <span>
+                <span class="far fa-comment fa-lg pr-1"></span> {{$status->comments_count}}
+                </span>
+              </h5>
+            </div>
           </div>
           </div>
-        </div>
-      </a>
-    </div>
+        </a>
+      </div>
     @endforeach
     @endforeach
+    </div>
+  </div>
+  <div class="pagination-container">
+    <div class="d-flex justify-content-center">
+      {{$timeline->links()}}
+    </div>
+  </div>
     @else
     @else
-    <div class="col-12">
-      <div class="card">
-        <div class="card-body py-5 my-5">
-          <div class="d-flex my-5 py-5 justify-content-center align-items-center">
-            <p class="lead font-weight-bold">{{ __('profile.emptyTimeline') }}</p>
+      <div class="col-12">
+        <div class="card">
+          <div class="card-body py-5 my-5">
+            <div class="d-flex my-5 py-5 justify-content-center align-items-center">
+              <p class="lead font-weight-bold">{{ __('profile.emptyTimeline') }}</p>
+            </div>
           </div>
           </div>
-        </div>
       </div>
       </div>
     </div>
     </div>
-    @endif
   </div>
   </div>
+    @endif
+
 </div>
 </div>
 
 
 @endsection
 @endsection
 
 
-@push('meta')
-<meta property="og:description" content="{{$user->bio}}">
-<meta property="og:image" content="{{$user->avatarUrl()}}">
+@push('meta')<meta property="og:description" content="{{$user->bio}}">
+    <meta property="og:image" content="{{$user->avatarUrl()}}">
+  @if(false == $settings->crawlable || $user->remote_url)
+  <meta name="robots" content="noindex, nofollow">
+  @endif
+@endpush
+
+@push('scripts')
+<script type="text/javascript">
+  $(document).ready(function() {
+    $('.pagination-container').hide();
+    $('.pagination').hide();
+    let elem = document.querySelector('.profile-timeline');
+    let infScroll = new InfiniteScroll( elem, {
+      path: '.pagination__next',
+      append: '.profile-timeline',
+      status: '.page-load-status',
+      history: false,
+    });
+  });
+</script>
+
 @endpush
 @endpush
 
 

+ 11 - 11
resources/views/settings/partial/sidebar.blade.php

@@ -1,44 +1,44 @@
   <div class="col-12 col-md-3 py-3" style="border-right:1px solid #ccc;">
   <div class="col-12 col-md-3 py-3" style="border-right:1px solid #ccc;">
     <ul class="nav flex-column settings-nav">
     <ul class="nav flex-column settings-nav">
       <li class="nav-item pl-3 {{request()->is('settings/home')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/home')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings')}}">Profile</a>
+        <a class="nav-link font-weight-light  text-muted" href="{{route('settings')}}">Profile</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/avatar')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/avatar')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.avatar')}}">Avatar</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.avatar')}}">Avatar</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/password')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/password')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.password')}}">Password</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.password')}}">Password</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/email')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/email')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.email')}}">Email</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.email')}}">Email</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/notifications')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/notifications')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.notifications')}}">Notifications</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.notifications')}}">Notifications</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/privacy')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/privacy')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.privacy')}}">Privacy</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.privacy')}}">Privacy</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/security')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/security')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.security')}}">Security</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">Security</a>
       </li>
       </li>
       <li class="nav-item">
       <li class="nav-item">
       <hr>
       <hr>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/import*')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/import*')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.import')}}">Import</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.import')}}">Import</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/data-export')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/data-export')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.dataexport')}}">Export</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.dataexport')}}">Export</a>
       </li>
       </li>
       </li>
       </li>
       <li class="nav-item">
       <li class="nav-item">
       <hr>
       <hr>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/applications')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/applications')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.applications')}}">Applications</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.applications')}}">Applications</a>
       </li>
       </li>
       <li class="nav-item pl-3 {{request()->is('settings/developers')?'active':''}}">
       <li class="nav-item pl-3 {{request()->is('settings/developers')?'active':''}}">
-        <a class="nav-link lead text-muted" href="{{route('settings.developers')}}">Developers</a>
+        <a class="nav-link font-weight-light text-muted" href="{{route('settings.developers')}}">Developers</a>
       </li>
       </li>
     </ul>
     </ul>
   </div>
   </div>

+ 26 - 3
resources/views/settings/privacy.blade.php

@@ -6,8 +6,31 @@
     <h3 class="font-weight-bold">Privacy Settings</h3>
     <h3 class="font-weight-bold">Privacy Settings</h3>
   </div>
   </div>
   <hr>
   <hr>
-  <div class="alert alert-danger">
-    Coming Soon
-  </div>
+  <form method="post">
+    @csrf
+    <div class="form-check pb-3">
+      <input class="form-check-input" type="checkbox" name="is_private" id="is_private" {{$settings->is_private ? 'checked=""':''}}>
+      <label class="form-check-label font-weight-bold" for="is_private">
+        {{__('Private Account')}}
+      </label>
+      <p class="text-muted small help-text">When your account is private, only people you approve can see your photos and videos on pixelfed. Your existing followers won't be affected.</p>
+    </div>
+    <div class="form-check pb-3">
+      <input class="form-check-input" type="checkbox" name="crawlable" id="crawlable" {{!$settings->crawlable ? 'checked=""':''}} {{$settings->is_private ? 'disabled=""':''}}>
+      <label class="form-check-label font-weight-bold" for="crawlable">
+        {{__('Opt-out of search engine indexing')}}
+      </label>
+      <p class="text-muted small help-text">When your account is visible to search engines, your information can be crawled and stored by search engines.</p>
+    </div>
+
+
+
+    <div class="form-group row mt-5 pt-5">
+      <div class="col-12 text-right">
+        <hr>
+        <button type="submit" class="btn btn-primary font-weight-bold">Submit</button>
+      </div>
+    </div>
+  </form>
 
 
 @endsection
 @endsection

+ 2 - 13
routes/web.php

@@ -1,17 +1,5 @@
 <?php
 <?php
 
 
-/*
-|--------------------------------------------------------------------------
-| Web Routes
-|--------------------------------------------------------------------------
-|
-| Here is where you can register web routes for your application. These
-| routes are loaded by the RouteServiceProvider within a group which
-| contains the "web" middleware group. Now create something great!
-|
-*/
-
-
 Route::domain(config('pixelfed.domain.admin'))->group(function() {
 Route::domain(config('pixelfed.domain.admin'))->group(function() {
   Route::redirect('/', '/dashboard');
   Route::redirect('/', '/dashboard');
   Route::redirect('timeline', config('app.url').'/timeline');
   Route::redirect('timeline', config('app.url').'/timeline');
@@ -91,6 +79,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware('validemail')->group(fu
     Route::get('email', 'SettingsController@email')->name('settings.email');
     Route::get('email', 'SettingsController@email')->name('settings.email');
     Route::get('notifications', 'SettingsController@notifications')->name('settings.notifications');
     Route::get('notifications', 'SettingsController@notifications')->name('settings.notifications');
     Route::get('privacy', 'SettingsController@privacy')->name('settings.privacy');
     Route::get('privacy', 'SettingsController@privacy')->name('settings.privacy');
+    Route::post('privacy', 'SettingsController@privacyStore');
     Route::get('security', 'SettingsController@security')->name('settings.security');
     Route::get('security', 'SettingsController@security')->name('settings.security');
     Route::get('applications', 'SettingsController@applications')->name('settings.applications');
     Route::get('applications', 'SettingsController@applications')->name('settings.applications');
     Route::get('data-export', 'SettingsController@dataExport')->name('settings.dataexport');
     Route::get('data-export', 'SettingsController@dataExport')->name('settings.dataexport');
@@ -137,4 +126,4 @@ Route::domain(config('pixelfed.domain.app'))->middleware('validemail')->group(fu
   Route::get('{username}/following', 'ProfileController@following');
   Route::get('{username}/following', 'ProfileController@following');
   Route::get('{username}', 'ProfileController@show');
   Route::get('{username}', 'ProfileController@show');
 
 
-});
+});