diff --git a/.env.example b/.env.example index 1dc6006a6..0e57b4318 100644 --- a/.env.example +++ b/.env.example @@ -48,19 +48,6 @@ MAX_CAPTION_LENGTH=150 MAX_ALBUM_LENGTH=4 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 config:cache - +AP_REMOTE_FOLLOW=false +AP_INBOX=false PF_COSTAR_ENABLED=false -CS_BLOCKED_DOMAINS='gab.com,gab.ai,develop.gab.com' -CS_CW_DOMAINS='switter.at' -CS_UNLISTED_DOMAINS='example.org,example.net,example.com' - -## Optional -#HORIZON_DARKMODE=false # Horizon theme darkmode -#HORIZON_EMBED=false # Single Docker Container mode diff --git a/CHANGELOG.md b/CHANGELOG.md index b67207b5e..08b3bfe2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,20 +3,33 @@ ## [Unreleased](https://github.com/pixelfed/pixelfed/compare/v0.10.3...dev) ### Added +- Added Welsh translations [#1706](https://github.com/pixelfed/pixelfed/pull/1706) +- Added Api v1 controller [85835f5a](https://github.com/pixelfed/pixelfed/commit/85835f5a6712dea0562df4be897087de5305750f) +- Added database migration that adds a language column to the users table [c87d8c16](https://github.com/pixelfed/pixelfed/commit/c87d8c16) +- Added persistent preferred language [18bc9c30](https://github.com/pixelfed/pixelfed/commit/18bc9c30) ### Fixed - Fixed count bug in StatusHashtagService [#1694](https://github.com/pixelfed/pixelfed/pull/1694) - Fixed private account bug [#1699](https://github.com/pixelfed/pixelfed/pull/1699) +- Fixed comments on MomentUI posts [#1704](https://github.com/pixelfed/pixelfed/pull/1704) ### Changed - Updated EmailService, added new domains [#1690](https://github.com/pixelfed/pixelfed/pull/1690) -- Updated quill.js to v1.3.7 [#1692](https://github.com/pixelfed/pixelfed/pull/1690) +- Updated quill.js to v1.3.7 [#1692](https://github.com/pixelfed/pixelfed/pull/1692) - Cache ProfileController [#1700](https://github.com/pixelfed/pixelfed/pull/1700) - Updated ComposeUI v4, made cropping optional [#1702](https://github.com/pixelfed/pixelfed/pull/1702) - Updated DiscoverController, limit Loops to local only posts [#1703](https://github.com/pixelfed/pixelfed/pull/1703) +- Namespaced internal apis [3c306c5e](https://github.com/pixelfed/pixelfed/commit/3c306c5e179d35dbe19a6a1bd9533350e4b96524) +- Updated .env.example with proper remote follow variable [0697f780](https://github.com/pixelfed/pixelfed/commit/0697f780d3a5cba72148f0a767d5a35124a3d9b4) +- Updated show all comments view [0a5eaa31](https://github.com/pixelfed/pixelfed/pull/1708/commits/0a5eaa3118cb09c61d3e5442fe3bf8439a2a12af) +- Updated language page layout [01fb5af](https://github.com/pixelfed/pixelfed/pull/1708/commits/01fb5af19e803488c5794b545d218771f6fce6d7) +- Updated privacy policy page layout [a4229d5](https://github.com/pixelfed/pixelfed/pull/1708/commits/a4229d5d30faea11e7a72d122c4a5762d867aaf3) +- Updated terms page layout [4f8c5e5](https://github.com/pixelfed/pixelfed/pull/1708/commits/4f8c5e5519949c63c702c724a00d8575db4e0014) +- Update v1 API, added /api/v1/instance endpoint [951b6fa0](https://github.com/pixelfed/pixelfed/commit/951b6fa0) [9dc2234b](https://github.com/pixelfed/pixelfed/commit/99dc2234b) ## Deprecated - Remove deprecated profile following/followers [#1697](https://github.com/pixelfed/pixelfed/pull/1697) +- Remove old comment permalink [05f6598](https://github.com/pixelfed/pixelfed/pull/1708/commits/05f659896d903e1ff41dba810f125d721fa057e7) ## [v0.10.3 (2019-09-08)](https://github.com/pixelfed/pixelfed/compare/v0.10.2...v0.10.3) @@ -43,7 +56,7 @@ ### Fixed -- Typo in Inbox prevented proper federation support +- Typo in Inbox prevented proper federation support [#1664](https://github.com/pixelfed/pixelfed/pull/1664) ## [v0.10.1 (2019-09-06)](https://github.com/pixelfed/pixelfed/compare/v0.10.0...v0.10.1) @@ -53,19 +66,19 @@ - Compose UI v4: a rework of the v3 flow to allow basic cropping and better support future post types - Profile badges show if a user is following you or is an admin - Show confirmation message when muting or blocking a user from a post -- Allow "read more" to be disabled on posts +- Allow "read more" to be disabled on posts [#1545](https://github.com/pixelfed/pixelfed/pull/1545) - Loops! Discover short videos - Preliminary support for profile PropertyValue metadata - Preliminary support for Direct Messages - Places! Run the artisan task `import:cities` - Emails are now validated and banned email domains are disallowed at signup. Artisan task `email:bancheck` will validate existing users. -- .env vars `REDIS_SCHEME` and `REDIS_PATH` allow for using Redis over a Unix socket instead of TCP +- .env vars `REDIS_SCHEME` and `REDIS_PATH` allow for using Redis over a Unix socket instead of TCP [#1602](https://github.com/pixelfed/pixelfed/pull/1602) - .env var `IMAGE_DRIVER` allows using imagick instead of gd ### Fixed -- Show delete button while composing video posts +- Show delete button while composing video posts [#1529](https://github.com/pixelfed/pixelfed/pull/1529) - Show pending follow requests on private profiles -- Allow muted users to comment on your posts +- Allow muted users to comment on your posts [#1537](https://github.com/pixelfed/pixelfed/pull/1537) - Bugs with carousel cursor and tooltips - Collections can now be deleted from collection page - Compose modal now indicates album media limits @@ -73,7 +86,7 @@ - Don't show Register link in navbar when registrations are closed ### Changed -- Use vue-masonry for Moment UI layout +- Use vue-masonry for Moment UI layout [#1536](https://github.com/pixelfed/pixelfed/pull/1536) - User post limit changed from 20/hr to 50/hr - Better mobile profile layout - Dark mode is now a bit bluer @@ -85,17 +98,17 @@ ## [v0.10.0 (2019-07-17)](https://github.com/pixelfed/pixelfed/compare/v0.9.6...v0.10.0) ### Added -- Collections! Add posts to Collections, similar to categories. -- Profile donate links: add links to Patreon, Liberapay, and OpenCollective on your profile +- Collections! Add posts to Collections, similar to categories. [#1511](https://github.com/pixelfed/pixelfed/pull/1511) +- Profile donate links: add links to Patreon, Liberapay, and OpenCollective on your profile [#1500](https://github.com/pixelfed/pixelfed/pull/1500) ### Fixed - Show correct mode when viewing followers / following ### Changed -- Profile model now uses snowflake id +- Profile model now uses snowflake id [#1502](https://github.com/pixelfed/pixelfed/pull/1502) ### Removed -- OStatus legacy code has been removed +- OStatus legacy code has been removed [#1510](https://github.com/pixelfed/pixelfed/pull/1510) ## [v0.9.6 (2019-07-10)](https://github.com/pixelfed/pixelfed/compare/v0.9.5...v0.9.6) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php new file mode 100644 index 000000000..3cc31514e --- /dev/null +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -0,0 +1,128 @@ +fractal = new Fractal\Manager(); + $this->fractal->setSerializer(new ArraySerializer()); + } + public function apps(Request $request) + { + abort_if(!config('pixelfed.oauth_enabled'), 404); + + $this->validate($request, [ + 'client_name' => 'required', + 'redirect_uris' => 'required', + 'scopes' => 'nullable', + 'website' => 'nullable' + ]); + + $client = Passport::client()->forceFill([ + 'user_id' => null, + 'name' => e($request->client_name), + 'secret' => Str::random(40), + 'redirect' => $request->redirect_uris, + 'personal_access_client' => false, + 'password_client' => false, + 'revoked' => false, + ]); + + $client->save(); + + $res = [ + 'id' => $client->id, + 'name' => $client->name, + 'website' => null, + 'redirect_uri' => $client->redirect, + 'client_id' => $client->id, + 'client_secret' => $client->secret, + 'vapid_key' => null + ]; + return $res; + } + + public function accountById(Request $request, $id) + { + $profile = Profile::whereNull('status')->findOrFail($id); + $resource = new Fractal\Resource\Item($profile, new AccountTransformer()); + $res = $this->fractal->createData($resource)->toArray(); + + return response()->json($res); + } + + public function statusById(Request $request, $id) + { + $status = Status::whereVisibility('public')->findOrFail($id); + $resource = new Fractal\Resource\Item($status, new StatusTransformer()); + $res = $this->fractal->createData($resource)->toArray(); + + return response()->json($res); + } + + public function instance(Request $request) + { + $res = [ + 'description' => 'Pixelfed - Photo sharing for everyone', + 'email' => config('instance.email'), + 'languages' => ['en'], + 'max_toot_chars' => config('pixelfed.max_caption_length'), + 'registrations' => config('pixelfed.open_registration'), + 'stats' => [ + 'user_count' => 0, + 'status_count' => 0, + 'domain_count' => 0 + ], + 'thumbnail' => config('app.url') . '/img/pixelfed-icon-color.png', + 'title' => 'Pixelfed (' . config('pixelfed.domain.app') . ')', + 'uri' => config('app.url'), + 'urls' => [], + 'version' => '2.7.2 (compatible; Pixelfed ' . config('pixelfed.version') . ')' + ]; + return response()->json($res, 200, [], JSON_PRETTY_PRINT); + } + + public function filters(Request $request) + { + // Pixelfed does not yet support keyword filters + return response()->json([]); + } + + public function context(Request $request) + { + // todo + $res = [ + 'ancestors' => [], + 'descendants' => [] + ]; + + return response()->json($res); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Api/BaseApiController.php b/app/Http/Controllers/Api/BaseApiController.php index 681126ff6..7874ed2db 100644 --- a/app/Http/Controllers/Api/BaseApiController.php +++ b/app/Http/Controllers/Api/BaseApiController.php @@ -40,40 +40,34 @@ class BaseApiController extends Controller public function __construct() { - $this->middleware('auth'); + // $this->middleware('auth'); $this->fractal = new Fractal\Manager(); $this->fractal->setSerializer(new ArraySerializer()); } public function notifications(Request $request) { - $pid = Auth::user()->profile->id; - $pg = $request->input('pg'); - if($pg == true) { - $timeago = Carbon::now()->subMonths(6); - $notifications = Notification::whereProfileId($pid) - ->whereDate('created_at', '>', $timeago) - ->latest() - ->simplePaginate(10); - $resource = new Fractal\Resource\Collection($notifications, new NotificationTransformer()); - $res = $this->fractal->createData($resource)->toArray(); - } else { - $this->validate($request, [ - 'page' => 'nullable|integer|min:1|max:10', - 'limit' => 'nullable|integer|min:1|max:10' - ]); - $limit = $request->input('limit') ?? 10; - $page = $request->input('page') ?? 1; - $end = (int) $page * $limit; - $start = (int) $end - $limit; - $res = NotificationService::get($pid, $start, $end); - } + abort_if(!$request->user(), 403); + $pid = $request->user()->profile_id; + $this->validate($request, [ + 'page' => 'nullable|integer|min:1|max:10', + 'limit' => 'nullable|integer|min:1|max:40' + ]); + $limit = $request->input('limit') ?? 10; + $timeago = Carbon::now()->subMonths(6); + $notifications = Notification::whereProfileId($pid) + ->whereDate('created_at', '>', $timeago) + ->latest() + ->simplePaginate($limit); + $resource = new Fractal\Resource\Collection($notifications, new NotificationTransformer()); + $res = $this->fractal->createData($resource)->toArray(); return response()->json($res); } public function accounts(Request $request, $id) { + abort_if(!$request->user(), 403); $profile = Profile::findOrFail($id); $resource = new Fractal\Resource\Item($profile, new AccountTransformer()); $res = $this->fractal->createData($resource)->toArray(); @@ -83,6 +77,7 @@ class BaseApiController extends Controller public function accountFollowers(Request $request, $id) { + abort_if(!$request->user(), 403); $profile = Profile::findOrFail($id); $followers = $profile->followers; $resource = new Fractal\Resource\Collection($followers, new AccountTransformer()); @@ -93,6 +88,7 @@ class BaseApiController extends Controller public function accountFollowing(Request $request, $id) { + abort_if(!$request->user(), 403); $profile = Profile::findOrFail($id); $following = $profile->following; $resource = new Fractal\Resource\Collection($following, new AccountTransformer()); @@ -103,6 +99,7 @@ class BaseApiController extends Controller public function accountStatuses(Request $request, $id) { + abort_if(!$request->user(), 403); $this->validate($request, [ 'only_media' => 'nullable', 'pinned' => 'nullable', @@ -152,6 +149,7 @@ class BaseApiController extends Controller public function avatarUpdate(Request $request) { + abort_if(!$request->user(), 403); $this->validate($request, [ 'upload' => 'required|mimes:jpeg,png,gif|max:'.config('pixelfed.max_avatar_size'), ]); @@ -188,6 +186,7 @@ class BaseApiController extends Controller public function showTempMedia(Request $request, int $profileId, $mediaId) { + abort_if(!$request->user(), 403); abort_if(!$request->hasValidSignature(), 404); abort_if(Auth::user()->profile_id !== $profileId, 404); $media = Media::whereProfileId(Auth::user()->profile_id)->findOrFail($mediaId); @@ -197,6 +196,7 @@ class BaseApiController extends Controller public function uploadMedia(Request $request) { + abort_if(!$request->user(), 403); $this->validate($request, [ 'file.*' => function() { return [ @@ -278,6 +278,7 @@ class BaseApiController extends Controller public function deleteMedia(Request $request) { + abort_if(!$request->user(), 403); $this->validate($request, [ 'id' => 'required|integer|min:1|exists:media,id' ]); @@ -299,12 +300,21 @@ class BaseApiController extends Controller public function verifyCredentials(Request $request) { + abort_if(!$request->user(), 403); $id = Auth::id(); $res = Cache::remember('user:account:id:'.$id, now()->addHours(6), function() use($id) { $profile = Profile::whereNull('status')->whereUserId($id)->firstOrFail(); $resource = new Fractal\Resource\Item($profile, new AccountTransformer()); - return $this->fractal->createData($resource)->toArray(); + $res = $this->fractal->createData($resource)->toArray(); + $res['source'] = [ + 'privacy' => $profile->is_private ? 'private' : 'public', + 'sensitive' => $profile->cw ? true : false, + 'language' => 'en', + 'note' => '', + 'fields' => [] + ]; + return $res; }); return response()->json($res); diff --git a/app/Http/Controllers/CommentController.php b/app/Http/Controllers/CommentController.php index 586aacc72..38c177562 100644 --- a/app/Http/Controllers/CommentController.php +++ b/app/Http/Controllers/CommentController.php @@ -21,21 +21,13 @@ use League\Fractal\Pagination\IlluminatePaginatorAdapter; class CommentController extends Controller { - public function show(Request $request, $username, int $id, int $cid) - { - $user = Profile::whereUsername($username)->firstOrFail(); - $status = Status::whereProfileId($user->id)->whereInReplyToId($id)->findOrFail($cid); - - return view('status.reply', compact('user', 'status')); - } - public function showAll(Request $request, $username, int $id) { - $user = Profile::whereUsername($username)->firstOrFail(); - $status = Status::whereProfileId($user->id)->findOrFail($id); - $replies = Status::whereInReplyToId($id)->paginate(40); + $profile = Profile::whereNull(['status', 'domain'])->whereUsername($username)->firstOrFail(); + $status = Status::whereProfileId($profile->id)->findOrFail($id); + $replies = Status::whereInReplyToId($id)->simplePaginate(40); - return view('status.comments', compact('user', 'status', 'replies')); + return view('status.comments', compact('profile', 'status', 'replies')); } public function store(Request $request) diff --git a/app/Http/Controllers/FederationController.php b/app/Http/Controllers/FederationController.php index e6edb11c6..eaaa1f583 100644 --- a/app/Http/Controllers/FederationController.php +++ b/app/Http/Controllers/FederationController.php @@ -129,7 +129,7 @@ class FederationController extends Controller $res['openRegistrations'] = config('pixelfed.open_registration'); return response()->json($res, 200, [ 'Access-Control-Allow-Origin' => '*' - ]); + ], JSON_PRETTY_PRINT); } public function webfinger(Request $request) diff --git a/app/Http/Controllers/FollowerController.php b/app/Http/Controllers/FollowerController.php index dfac38ce4..97a3700d2 100644 --- a/app/Http/Controllers/FollowerController.php +++ b/app/Http/Controllers/FollowerController.php @@ -38,7 +38,6 @@ class FollowerController extends Controller { $user = Auth::user()->profile; - $target = Profile::where('id', '!=', $user->id)->whereNull('status')->findOrFail($item); $private = (bool) $target->is_private; $remote = (bool) $target->domain; @@ -54,7 +53,7 @@ class FollowerController extends Controller $isFollowing = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->exists(); - if($private == true && $isFollowing == 0 || $remote == true) { + if($private == true && $isFollowing == 0 && $remote == true) { if($user->following()->count() >= Follower::MAX_FOLLOWING) { abort(400, 'You cannot follow more than ' . Follower::MAX_FOLLOWING . ' accounts'); } diff --git a/app/Http/Controllers/PublicApiController.php b/app/Http/Controllers/PublicApiController.php index 41cc2b3d9..dee909acf 100644 --- a/app/Http/Controllers/PublicApiController.php +++ b/app/Http/Controllers/PublicApiController.php @@ -223,7 +223,7 @@ class PublicApiController extends Controller 'page' => 'nullable|integer|max:40', 'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, 'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, - 'limit' => 'nullable|integer|max:20' + 'limit' => 'nullable|integer|max:30' ]); if(config('instance.timeline.local.is_public') == false && !Auth::check()) { @@ -332,7 +332,7 @@ class PublicApiController extends Controller 'page' => 'nullable|integer|max:40', 'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, 'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, - 'limit' => 'nullable|integer|max:20' + 'limit' => 'nullable|integer|max:40' ]); $page = $request->input('page'); diff --git a/app/Http/Controllers/Settings/HomeSettings.php b/app/Http/Controllers/Settings/HomeSettings.php index b63cedee8..aaf063c3a 100644 --- a/app/Http/Controllers/Settings/HomeSettings.php +++ b/app/Http/Controllers/Settings/HomeSettings.php @@ -38,12 +38,14 @@ trait HomeSettings 'name' => 'required|string|max:'.config('pixelfed.max_name_length'), 'bio' => 'nullable|string|max:'.config('pixelfed.max_bio_length'), 'website' => 'nullable|url', + 'language' => 'nullable|string|min:2|max:5' ]); $changes = false; $name = strip_tags(Purify::clean($request->input('name'))); $bio = $request->filled('bio') ? strip_tags(Purify::clean($request->input('bio'))) : null; $website = $request->input('website'); + $language = $request->input('language'); $user = Auth::user(); $profile = $user->profile; $layout = $request->input('profile_layout'); @@ -51,10 +53,10 @@ trait HomeSettings $layout = !in_array($layout, ['metro', 'moment']) ? 'metro' : $layout; } - $validate = config('pixelfed.enforce_email_verification'); + $enforceEmailVerification = config('pixelfed.enforce_email_verification'); // Only allow email to be updated if not yet verified - if (!$validate || !$changes && $user->email_verified_at) { + if (!$enforceEmailVerification || !$changes && $user->email_verified_at) { if ($profile->name != $name) { $changes = true; $user->name = $name; @@ -71,9 +73,12 @@ trait HomeSettings $profile->bio = $bio; } - if ($profile->profile_layout != $layout) { + if($user->language != $language && + in_array($language, \App\Util\Localization\Localization::languages()) + ) { $changes = true; - $profile->profile_layout = $layout; + $user->language = $language; + session()->put('locale', $language); } } diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index f552013d5..b7d2bdb19 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -34,6 +34,11 @@ class SiteController extends Controller // todo: add other locales after pushing new l10n strings $locales = Localization::languages(); if(in_array($locale, $locales)) { + if($request->user()) { + $user = $request->user(); + $user->language = $locale; + $user->save(); + } session()->put('locale', $locale); } diff --git a/app/Listeners/AuthLogin.php b/app/Listeners/AuthLogin.php index fab7ff6d6..bd38eee4a 100644 --- a/app/Listeners/AuthLogin.php +++ b/app/Listeners/AuthLogin.php @@ -36,6 +36,7 @@ class AuthLogin $this->userState($user); $this->userDevice($user); $this->userProfileId($user); + $this->userLanguage($user); } protected function userProfile($user) @@ -132,4 +133,9 @@ class AuthLogin }); } } + + protected function userLanguage($user) + { + session()->put('locale', $user->language ?? 'en'); + } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 968c4cfa6..6f077f832 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -4,6 +4,7 @@ namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Laravel\Passport\Passport; +use Gate; class AuthServiceProvider extends ServiceProvider { @@ -32,14 +33,22 @@ class AuthServiceProvider extends ServiceProvider Passport::enableImplicitGrant(); Passport::setDefaultScope([ - 'user:read', - 'user:write' + 'read', + 'write', + 'follow', + 'push' ]); Passport::tokensCan([ - 'user:read' => 'Read a user’s profile info and media', - 'user:write' => 'This scope lets an app "Change your profile information"', + 'read' => 'Full read access to your account', + 'write' => 'Full write access to your account', + 'follow' => 'Ability to follow other profiles', + 'push' => '' ]); } + + Gate::define('viewWebSocketsDashboard', function ($user = null) { + return $user->is_admin; + }); } } diff --git a/app/Transformer/Api/AccountTransformer.php b/app/Transformer/Api/AccountTransformer.php index eb3e819cb..53b49c38a 100644 --- a/app/Transformer/Api/AccountTransformer.php +++ b/app/Transformer/Api/AccountTransformer.php @@ -14,29 +14,32 @@ class AccountTransformer extends Fractal\TransformerAbstract public function transform(Profile $profile) { - $is_admin = $profile->domain ? false : $profile->user->is_admin; + $local = $profile->domain == null; + $is_admin = !$local ? false : $profile->user->is_admin; + $acct = $local ? $profile->username : substr($profile->username, 1); + $username = $local ? $profile->username : explode('@', $acct)[0]; return [ 'id' => (string) $profile->id, - 'username' => $profile->username, - 'acct' => $profile->username, + 'username' => $username, + 'acct' => $acct, 'display_name' => $profile->name, 'locked' => (bool) $profile->is_private, - 'created_at' => null, + 'created_at' => $profile->created_at->format('c'), 'followers_count' => $profile->followerCount(), 'following_count' => $profile->followingCount(), 'statuses_count' => (int) $profile->statusCount(), - 'note' => $profile->bio, + 'note' => $profile->bio ?? '', 'url' => $profile->url(), 'avatar' => $profile->avatarUrl(), 'avatar_static' => $profile->avatarUrl(), - 'header' => null, - 'header_static' => null, + 'header' => '', + 'header_static' => '', 'header_bg' => $profile->header_bg, + 'emojis' => [], 'moved' => null, - 'fields' => null, - 'bot' => null, + 'fields' => [], + 'bot' => false, 'website' => $profile->website, - 'software' => 'pixelfed', 'is_admin' => (bool) $is_admin, ]; } diff --git a/app/Transformer/Api/NotificationTransformer.php b/app/Transformer/Api/NotificationTransformer.php index 0408eeea8..c9616632d 100644 --- a/app/Transformer/Api/NotificationTransformer.php +++ b/app/Transformer/Api/NotificationTransformer.php @@ -22,8 +22,6 @@ class NotificationTransformer extends Fractal\TransformerAbstract 'id' => (string) $notification->id, 'type' => $this->replaceTypeVerb($notification->action), 'created_at' => (string) $notification->created_at->format('c'), - 'account' => null, - 'status' => null ]; } diff --git a/database/migrations/2019_09_21_015556_add_language_to_users_table.php b/database/migrations/2019_09_21_015556_add_language_to_users_table.php new file mode 100644 index 000000000..6bbfa8082 --- /dev/null +++ b/database/migrations/2019_09_21_015556_add_language_to_users_table.php @@ -0,0 +1,32 @@ +string('language')->nullable()->index()->after('status'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('language'); + }); + } +} diff --git a/public/img/pixelfed-icon-color.png b/public/img/pixelfed-icon-color.png new file mode 100644 index 000000000..6e0efdaaa Binary files /dev/null and b/public/img/pixelfed-icon-color.png differ diff --git a/public/js/activity.js b/public/js/activity.js index 104bd14de..d6e4fbad0 100644 Binary files a/public/js/activity.js and b/public/js/activity.js differ diff --git a/public/js/collectioncompose.js b/public/js/collectioncompose.js index 08e29ca59..b7b1e131e 100644 Binary files a/public/js/collectioncompose.js and b/public/js/collectioncompose.js differ diff --git a/public/js/collections.js b/public/js/collections.js index adacc760e..28d14f1ce 100644 Binary files a/public/js/collections.js and b/public/js/collections.js differ diff --git a/public/js/compose-classic.js b/public/js/compose-classic.js index 2fc110c35..64a1d15e0 100644 Binary files a/public/js/compose-classic.js and b/public/js/compose-classic.js differ diff --git a/public/js/compose.js b/public/js/compose.js index d582761d2..f4752f38f 100644 Binary files a/public/js/compose.js and b/public/js/compose.js differ diff --git a/public/js/profile.js b/public/js/profile.js index 852acb1df..fa20e30ba 100644 Binary files a/public/js/profile.js and b/public/js/profile.js differ diff --git a/public/js/status.js b/public/js/status.js index 538b4d4b0..9d3c4a2fd 100644 Binary files a/public/js/status.js and b/public/js/status.js differ diff --git a/public/js/timeline.js b/public/js/timeline.js index c14f016d6..fe8a0582e 100644 Binary files a/public/js/timeline.js and b/public/js/timeline.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 41f96d0db..344c2149b 100644 Binary files a/public/mix-manifest.json and b/public/mix-manifest.json differ diff --git a/resources/assets/js/components/Activity.vue b/resources/assets/js/components/Activity.vue index 8cc8f586c..654e67ebf 100644 --- a/resources/assets/js/components/Activity.vue +++ b/resources/assets/js/components/Activity.vue @@ -115,7 +115,7 @@ export default { methods: { fetchNotifications() { - axios.get('/api/v1/notifications') + axios.get('/api/pixelfed/v1/notifications') .then(res => { let data = res.data.filter(n => { if(n.type == 'share' && !status) { @@ -136,7 +136,7 @@ export default { $state.complete(); return; } - axios.get('/api/v1/notifications', { + axios.get('/api/pixelfed/v1/notifications', { params: { page: this.notificationCursor } diff --git a/resources/assets/js/components/CollectionComponent.vue b/resources/assets/js/components/CollectionComponent.vue index 733601ba0..56dd8318f 100644 --- a/resources/assets/js/components/CollectionComponent.vue +++ b/resources/assets/js/components/CollectionComponent.vue @@ -125,7 +125,7 @@ export default { methods: { fetchCurrentUser() { if(document.querySelectorAll('body')[0].classList.contains('loggedIn') == true) { - axios.get('/api/v1/accounts/verify_credentials').then(res => { + axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => { this.currentUser = res.data; this.owner = this.currentUser.id == this.profileId; }); diff --git a/resources/assets/js/components/CollectionCompose.vue b/resources/assets/js/components/CollectionCompose.vue index 9ae7de01e..7ba4cb1d3 100644 --- a/resources/assets/js/components/CollectionCompose.vue +++ b/resources/assets/js/components/CollectionCompose.vue @@ -201,7 +201,7 @@ export default { }, fetchRecentPosts() { - axios.get('/api/v1/accounts/' + this.profileId + '/statuses', { + axios.get('/api/local/accounts/' + this.profileId + '/statuses', { params: { only_media: true, min_id: 1, diff --git a/resources/assets/js/components/ComposeClassic.vue b/resources/assets/js/components/ComposeClassic.vue index df751cb71..24f49ea8c 100644 --- a/resources/assets/js/components/ComposeClassic.vue +++ b/resources/assets/js/components/ComposeClassic.vue @@ -295,7 +295,7 @@ export default { methods: { fetchProfile() { - axios.get('/api/v1/accounts/verify_credentials').then(res => { + axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => { this.profile = res.data; if(res.data.locked == true) { this.visibility = 'private'; @@ -341,7 +341,7 @@ export default { } }; - axios.post('/api/v1/media', form, xhrConfig) + axios.post('/api/pixelfed/v1/media', form, xhrConfig) .then(function(e) { self.uploadProgress = 100; self.ids.push(e.data.id); @@ -373,7 +373,7 @@ export default { return; } let id = this.media[this.carouselCursor].id; - axios.delete('/api/v1/media', { + axios.delete('/api/pixelfed/v1/media', { params: { id: id } diff --git a/resources/assets/js/components/ComposeModal.vue b/resources/assets/js/components/ComposeModal.vue index 99c3df1b1..5ee92427b 100644 --- a/resources/assets/js/components/ComposeModal.vue +++ b/resources/assets/js/components/ComposeModal.vue @@ -400,7 +400,7 @@ export default { methods: { fetchProfile() { - axios.get('/api/v1/accounts/verify_credentials').then(res => { + axios.get('/api/pixelfed/v1/accounts/verify_credentials').then(res => { this.profile = res.data; window.pixelfed.currentUser = res.data; if(res.data.locked == true) { @@ -454,7 +454,7 @@ export default { } }; - axios.post('/api/v1/media', form, xhrConfig) + axios.post('/api/pixelfed/v1/media', form, xhrConfig) .then(function(e) { self.uploadProgress = 100; self.ids.push(e.data.id); @@ -516,7 +516,7 @@ export default { return; } let id = this.media[this.carouselCursor].id; - axios.delete('/api/v1/media', { + axios.delete('/api/pixelfed/v1/media', { params: { id: id } diff --git a/resources/assets/js/components/NotificationCard.vue b/resources/assets/js/components/NotificationCard.vue index 8dc685a16..de90195e2 100644 --- a/resources/assets/js/components/NotificationCard.vue +++ b/resources/assets/js/components/NotificationCard.vue @@ -81,7 +81,7 @@ methods: { fetchNotifications() { - axios.get('/api/v1/notifications') + axios.get('/api/pixelfed/v1/notifications') .then(res => { let data = res.data.filter(n => { if(n.type == 'share' && !status) { @@ -103,7 +103,7 @@ $state.complete(); return; } - axios.get('/api/v1/notifications', { + axios.get('/api/pixelfed/v1/notifications', { params: { page: this.notificationCursor } @@ -171,7 +171,7 @@ let interval = this.notifications.length > 5 ? 15000 : 120000; let self = this; setInterval(function() { - axios.get('/api/v1/notifications') + axios.get('/api/pixelfed/v1/notifications') .then(res => { let data = res.data.filter(n => { if(n.type == 'share' || self.notificationMaxId >= n.id) { diff --git a/resources/assets/js/components/PostComponent.vue b/resources/assets/js/components/PostComponent.vue index b5316e314..403c775bb 100644 --- a/resources/assets/js/components/PostComponent.vue +++ b/resources/assets/js/components/PostComponent.vue @@ -370,7 +370,7 @@ {{timeAgo(reply.created_at)}} -
+