浏览代码

Merge pull request #1807 from pixelfed/staging

Staging
daniel 5 年之前
父节点
当前提交
3b52f809f9
共有 49 个文件被更改,包括 606 次插入414 次删除
  1. 2 1
      .circleci/config.yml
  2. 4 0
      CHANGELOG.md
  3. 6 1
      CONTRIBUTING.md
  4. 0 1
      Dockerfile
  5. 1 1
      app/Providers/AuthServiceProvider.php
  6. 17 0
      app/Story.php
  7. 20 1
      app/StoryItem.php
  8. 2 0
      app/StoryView.php
  9. 1 0
      app/Transformer/Api/AccountTransformer.php
  10. 8 0
      app/Util/Site/Config.php
  11. 8 8
      composer.json
  12. 276 275
      composer.lock
  13. 7 1
      config/instance.php
  14. 1 1
      contrib/docker/Dockerfile.apache
  15. 1 1
      contrib/docker/Dockerfile.fpm
  16. 1 0
      contrib/nginx.conf
  17. 9 2
      docker-compose.yml
  18. 5 0
      package-lock.json
  19. 3 9
      package.json
  20. 二进制
      public/css/app.css
  21. 二进制
      public/css/appdark.css
  22. 二进制
      public/css/landing.css
  23. 二进制
      public/js/app.js
  24. 二进制
      public/js/collections.js
  25. 二进制
      public/js/profile.js
  26. 二进制
      public/js/status.js
  27. 二进制
      public/js/timeline.js
  28. 二进制
      public/mix-manifest.json
  29. 6 6
      resources/assets/js/app.js
  30. 54 5
      resources/assets/js/components/CollectionComponent.vue
  31. 18 2
      resources/assets/js/components/Profile.vue
  32. 65 15
      resources/assets/js/components/Timeline.vue
  33. 0 32
      resources/assets/js/components/presenter/PhotoAlbumPresenter.vue
  34. 15 2
      resources/assets/js/components/presenter/VideoPresenter.vue
  35. 0 4
      resources/assets/sass/app.scss
  36. 0 4
      resources/assets/sass/appdark.scss
  37. 4 0
      resources/assets/sass/custom.scss
  38. 1 1
      resources/lang/de/auth.php
  39. 1 1
      resources/lang/de/helpcenter.php
  40. 3 3
      resources/lang/de/notification.php
  41. 3 3
      resources/lang/de/passwords.php
  42. 5 5
      resources/lang/de/profile.php
  43. 2 2
      resources/lang/de/site.php
  44. 46 6
      resources/views/layouts/app.blade.php
  45. 2 2
      resources/views/settings/partial/sidebar.blade.php
  46. 4 1
      resources/views/status/show.blade.php
  47. 1 1
      routes/api.php
  48. 3 3
      routes/web.php
  49. 1 14
      tests/Feature/LoginTest.php

+ 2 - 1
.circleci/config.yml

@@ -41,7 +41,8 @@ jobs:
           paths:
             - vendor
 
-      - run: cp .env.example .env
+      - run: cp .env.testing .env
+      - run: php artisan route:clear
       - run: php artisan storage:link
       - run: php artisan key:generate
       - run: php artisan config:clear

+ 4 - 0
CHANGELOG.md

@@ -37,6 +37,10 @@
 - Updated StatusHashtagService, reduce cached hashtag count ttl from 6 hours to 5 minutes ([126886e8](https://github.com/pixelfed/pixelfed/commit/126886e8))
 - Updated Hashtag.vue component, added formatted posts count ([c71f3dd1](https://github.com/pixelfed/pixelfed/commit/c71f3dd1))
 - Updated FixLikes command, fix postgres support ([771f9c46](https://github.com/pixelfed/pixelfed/commit/771f9c46))
+- Updated Settings, hide sponsors feature until re-implemented in Profile UI ([c4dd8449](https://github.com/pixelfed/pixelfed/commit/c4dd8449))
+- Updated Status view, added ```video``` open graph tag support ([#1799](https://github.com/pixelfed/pixelfed/pull/1799))
+- Updated AccountTransformer, added ```local``` attribute ([d2a90f11](https://github.com/pixelfed/pixelfed/commit/d2a90f11))
+- Updated Laravel framework from v5.8 to v6.x ([3aff6de33](https://github.com/pixelfed/pixelfed/commit/3aff6de33))
 
 ## Deprecated
     

+ 6 - 1
CONTRIBUTING.md

@@ -10,8 +10,13 @@ Remember, bug reports are created in the hope that others with the same problem
 ## Core Development Discussion
 Informal discussion regarding bugs, new features, and implementation of existing features takes place in the ```#pixelfed-dev``` channel on the Freenode IRC network.
 
+## Branches
+If you want to contribute to this repository, please file your pull request against the `staging` branch. 
+
+Pixelfed Beta currently uses the `dev` branch for deployable code. When v1.0 is released, the stable branch will be changed to `master`, with `dev` branch being used for development and testing.
+
 ## Compiled Assets
 If you are submitting a change that will affect a compiled file, such as most of the files in ```resources/assets/sass``` or ```resources/assets/js``` of the pixelfed/pixelfed repository, do not commit the compiled files. Due to their large size, they cannot realistically be reviewed by a maintainer. This could be exploited as a way to inject malicious code into Pixelfed. In order to defensively prevent this, all compiled files will be generated and committed by Pixelfed maintainers.
 
 ## Security Vulnerabilities
-If you discover a security vulnerability within Pixelfed, please send an email to Daniel Supernault at hello@pixelfed.org. All security vulnerabilities will be promptly addressed.
+If you discover a security vulnerability within Pixelfed, please send an email to Daniel Supernault at hello@pixelfed.org. All security vulnerabilities will be promptly addressed.

+ 0 - 1
Dockerfile

@@ -1 +0,0 @@
-contrib/docker/Dockerfile.apache

+ 1 - 1
app/Providers/AuthServiceProvider.php

@@ -27,7 +27,7 @@ class AuthServiceProvider extends ServiceProvider
         $this->registerPolicies();
 
         if(config('pixelfed.oauth_enabled')) {
-            Passport::routes(null, ['middleware' => [ \Barryvdh\Cors\HandleCors::class ]]);
+            Passport::routes(null, ['middleware' => ['twofactor', \Barryvdh\Cors\HandleCors::class]]);
             Passport::tokensExpireIn(now()->addDays(15));
             Passport::refreshTokensExpireIn(now()->addDays(30));
             Passport::enableImplicitGrant();

+ 17 - 0
app/Story.php

@@ -4,9 +4,26 @@ namespace App;
 
 use Auth;
 use Illuminate\Database\Eloquent\Model;
+use Pixelfed\Snowflake\HasSnowflakePrimary;
 
 class Story extends Model
 {
+    use HasSnowflakePrimary;
+
+    /**
+     * Indicates if the IDs are auto-incrementing.
+     *
+     * @var bool
+     */
+    public $incrementing = false;
+
+    /**
+     * The attributes that should be mutated to dates.
+     *
+     * @var array
+     */
+    protected $dates = ['published_at', 'expires_at'];
+
 	protected $visible = ['id'];
 
 	public function profile()

+ 20 - 1
app/StoryItem.php

@@ -3,10 +3,29 @@
 namespace App;
 
 use Illuminate\Database\Eloquent\Model;
+use Pixelfed\Snowflake\HasSnowflakePrimary;
 use Storage;
 
 class StoryItem extends Model
 {
+	use HasSnowflakePrimary;
+
+	/**
+	* Indicates if the IDs are auto-incrementing.
+	*
+	* @var bool
+	*/
+	public $incrementing = false;
+
+	/**
+	* The attributes that should be mutated to dates.
+	*
+	* @var array
+	*/
+	protected $dates = ['expires_at'];
+
+	protected $visible = ['id'];
+
 	public function story()
 	{
 		return $this->belongsTo(Story::class);
@@ -14,6 +33,6 @@ class StoryItem extends Model
 
 	public function url()
 	{
-		return Storage::url($this->media_path);
+		return url(Storage::url($this->media_path));
 	}
 }

+ 2 - 0
app/StoryView.php

@@ -6,6 +6,8 @@ use Illuminate\Database\Eloquent\Model;
 
 class StoryView extends Model
 {
+	public $fillable = ['story_id', 'profile_id'];
+	
 	public function story()
 	{
 		return $this->belongsTo(Story::class);

+ 1 - 0
app/Transformer/Api/AccountTransformer.php

@@ -31,6 +31,7 @@ class AccountTransformer extends Fractal\TransformerAbstract
 			'url' => $profile->url(),
 			'avatar' => $profile->avatarUrl(),
 			'website' => $profile->website,
+			'local' => (bool) $local,
 			'is_admin' => (bool) $is_admin,
 		];
 	}

+ 8 - 0
app/Util/Site/Config.php

@@ -36,6 +36,14 @@ class Config {
 				'site' => [
 					'domain' => config('pixelfed.domain.app'),
 					'url'    => config('app.url')
+				],
+
+				'username' => [
+					'remote' => [
+						'formats' => config('instance.username.remote.formats'),
+						'format' => config('instance.username.remote.format'),
+						'custom' => config('instance.username.remote.custom')
+					]
 				]
 			];
 		});

+ 8 - 8
composer.json

@@ -5,7 +5,7 @@
     "license": "AGPL-3.0-only",
     "type": "project",
     "require": {
-        "php": "^7.1.3",
+        "php": "^7.2",
         "ext-bcmath": "*",
         "ext-ctype": "*",
         "ext-curl": "*",
@@ -19,7 +19,8 @@
         "fideloper/proxy": "^4.0",
         "intervention/image": "^2.4",
         "jenssegers/agent": "^2.6",
-        "laravel/framework": "5.8.*",
+        "laravel/framework": "^6.0",
+        "laravel/helpers": "^1.1",
         "laravel/horizon": "^3.3",
         "laravel/passport": "^7.0",
         "laravel/tinker": "^1.0",
@@ -27,10 +28,9 @@
         "league/flysystem-cached-adapter": "~1.0",
         "league/iso3166": "^2.1",
         "moontoast/math": "^1.1",
-        "pbmedia/laravel-ffmpeg": "4.0.0",
+        "pbmedia/laravel-ffmpeg": "5.0.*",
         "phpseclib/phpseclib": "~2.0",
         "pixelfed/bacon-qr-code": "^3.0",
-        "pixelfed/dotenv-editor": "^2.0",
         "pixelfed/fractal": "^0.18.0",
         "pixelfed/google2fa": "^4.0",
         "pixelfed/laravel-snowflake": "^2.0",
@@ -38,16 +38,16 @@
         "predis/predis": "^1.1",
         "spatie/laravel-backup": "^6.0.0",
         "spatie/laravel-image-optimizer": "^1.1",
-        "stevebauman/purify": "2.0.*"
+        "stevebauman/purify": "3.0.*"
     },
     "require-dev": {
         "barryvdh/laravel-debugbar": "dev-master",
-        "filp/whoops": "^2.0",
+        "facade/ignition": "^1.4",
         "fzaninotto/faker": "^1.4",
         "mockery/mockery": "^1.0",
-        "nunomaduro/collision": "^2.0",
+        "nunomaduro/collision": "^3.0",
         "nunomaduro/phpinsights": "^1.7",
-        "phpunit/phpunit": "^7.5"
+        "phpunit/phpunit": "^8.0"
     },
     "autoload": {
         "classmap": [

文件差异内容过多而无法显示
+ 276 - 275
composer.lock


+ 7 - 1
config/instance.php

@@ -39,5 +39,11 @@ return [
 			'body' => env('PAGE_503_BODY', 'Our service is in maintenance mode, please try again later.')
 		]
 	],
-
+	'username' => [
+		'remote' => [
+			'formats' => ['@', 'from', 'custom'],
+			'format' => in_array(env('USERNAME_REMOTE_FORMAT', '@'), ['@','from','custom']) ? env('USERNAME_REMOTE_FORMAT', '@') : '@',
+			'custom' => env('USERNAME_REMOTE_CUSTOM_TEXT', null)
+		]
+	],
 ];

+ 1 - 1
contrib/docker/Dockerfile.apache

@@ -8,7 +8,7 @@ RUN apt-get update \
  && apt-get install -y --no-install-recommends git gosu \
       optipng pngquant jpegoptim gifsicle libpq-dev libsqlite3-dev locales zip unzip libzip-dev libcurl4-openssl-dev \
       libfreetype6 libicu-dev libjpeg62-turbo libpng16-16 libxpm4 libwebp6 libmagickwand-6.q16-6 \
-      libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libwebp-dev libmagickwand-dev \
+      libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libwebp-dev libmagickwand-dev mariadb-client\
  && sed -i '/en_US/s/^#//g' /etc/locale.gen \
  && locale-gen && update-locale \
  && docker-php-source extract \

+ 1 - 1
contrib/docker/Dockerfile.fpm

@@ -8,7 +8,7 @@ RUN apt-get update \
  && apt-get install -y --no-install-recommends git gosu \
       optipng pngquant jpegoptim gifsicle libpq-dev libsqlite3-dev locales zip unzip libzip-dev libcurl4-openssl-dev \
       libfreetype6 libicu-dev libjpeg62-turbo libpng16-16 libxpm4 libwebp6 libmagickwand-6.q16-6 \
-      libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libwebp-dev libmagickwand-dev \
+      libfreetype6-dev libjpeg62-turbo-dev libpng-dev libxpm-dev libwebp-dev libmagickwand-dev mariadb-client\
  && sed -i '/en_US/s/^#//g' /etc/locale.gen \
  && locale-gen && update-locale \
  && docker-php-source extract \

+ 1 - 0
contrib/nginx.conf

@@ -30,6 +30,7 @@ server {
 
     location ~ \.php$ {
         fastcgi_split_path_info ^(.+\.php)(/.+)$;
+        try_files $fastcgi_script_name =404;
         fastcgi_pass unix:/run/php-fpm/php-fpm.sock; # make sure this is correct
         fastcgi_index index.php;
         include fastcgi_params;

+ 9 - 2
docker-compose.yml

@@ -14,7 +14,10 @@ services:
 
   app:
     # Comment to use dockerhub image
-    build: .
+    build:
+      context: .
+      dockerfile: contrib/docker/Dockerfile.apache
+      #dockerfile: contrib/docker/Dockerfile.fpm
     image: pixelfed
     restart: unless-stopped
     ## If you have a traefik running, uncomment this to expose Pixelfed
@@ -36,7 +39,10 @@ services:
 
   worker:  # Comment this whole block if HORIZON_EMBED is true.
     # Comment to use dockerhub image
-    build: .
+    build:
+      context: .
+      dockerfile: contrib/docker/Dockerfile.apache
+      #dockerfile: contrib/docker/Dockerfile.fpm
     image: pixelfed
     restart: unless-stopped
     env_file:
@@ -54,6 +60,7 @@ services:
     restart: unless-stopped
     networks:
       - internal
+    command: --default-authentication-plugin=mysql_native_password
     environment:
       - MYSQL_DATABASE=pixelfed
       - MYSQL_USER=${DB_USERNAME}

+ 5 - 0
package-lock.json

@@ -10484,6 +10484,11 @@
             "version": "0.1.2",
             "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
             "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
+        },
+        "zuck.js": {
+            "version": "1.5.4",
+            "resolved": "https://registry.npmjs.org/zuck.js/-/zuck.js-1.5.4.tgz",
+            "integrity": "sha512-vCNaP+mLHzslUJrIj3FakFfno9wKWJatlTKYCW7EjxN4xkodfEIcm5QrE+J9UdPSTn9TTaXrDRgaJZeG3Er7HA=="
         }
     }
 }

+ 3 - 9
package.json

@@ -8,8 +8,7 @@
         "watch-poll": "npm run watch -- --watch-poll",
         "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
         "prod": "npm run production",
-        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
-        "postinstall": "opencollective-postinstall"
+        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
     },
     "devDependencies": {
         "axios": "^0.18.1",
@@ -28,21 +27,15 @@
     "dependencies": {
         "@trevoreyre/autocomplete-vue": "^2.0.2",
         "bootstrap-vue": "^2.0.0-rc.26",
-        "emoji-mart-vue": "^2.6.6",
         "filesize": "^3.6.1",
         "howler": "^2.1.2",
         "infinite-scroll": "^3.0.6",
         "laravel-echo": "^1.5.4",
         "laravel-mix": "^4.1.2",
         "node-sass": "^4.12.0",
-        "opencollective": "^1.0.3",
-        "opencollective-postinstall": "^2.0.2",
-        "plyr": "^3.5.6",
         "promise-polyfill": "8.1.0",
-        "pusher-js": "^4.4.0",
         "quill": "^1.3.7",
         "readmore-js": "^2.2.1",
-        "socket.io-client": "^2.2.0",
         "sweetalert": "^2.1.2",
         "twitter-text": "^2.0.5",
         "vue-carousel": "^0.18.0",
@@ -50,7 +43,8 @@
         "vue-cropperjs": "^4.0.0",
         "vue-infinite-loading": "^2.4.4",
         "vue-loading-overlay": "^3.2.0",
-        "vue-timeago": "^5.1.2"
+        "vue-timeago": "^5.1.2",
+        "zuck.js": "^1.5.4"
     },
     "collective": {
         "type": "opencollective",

二进制
public/css/app.css


二进制
public/css/appdark.css


二进制
public/css/landing.css


二进制
public/js/app.js


二进制
public/js/collections.js


二进制
public/js/profile.js


二进制
public/js/status.js


二进制
public/js/timeline.js


二进制
public/mix-manifest.json


+ 6 - 6
resources/assets/js/app.js

@@ -20,19 +20,18 @@ window.App.boot = function() {
 	new Vue({ el: '#content'});
 }
 
+
 window.App.util = {
 	time: (function() { 
 		return new Date; 
 	}),
-	version: (function() {
-		return 1;
-	}),
+	version: 1,
 	format: {
-		count: (function(count = 0) {
+		count: (function(count = 0, locale = 'en-GB', notation = 'compact') {
 			if(count < 1) {
 				return 0;
 			}
-			return new Intl.NumberFormat('en-GB', { notation: "compact" , compactDisplay: "short" }).format(count);
+			return new Intl.NumberFormat(locale, { notation: notation , compactDisplay: "short" }).format(count);
 		})
 	}, 
 	filters: [
@@ -78,5 +77,6 @@ window.App.util = {
 			['Willow','filter-willow'], 
 			['X-Pro II','filter-xpro-ii']
 		],
-		emoji: ['😂','💯','❤️','🙌','👏','👌','😍','😯','😢','😅','😁','🙂','😎','😀','🤣','😃','😄','😆','😉','😊','😋','😘','😗','😙','😚','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😪','😫','😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','🙁','😖','😞','😟','😤','😭','😦','😧','😨','😩','🤯','😬','😰','😱','😳','🤪','😵','😡','😠','🤬','😷','🤒','🤕','🤢','🤮','🤧','😇','🤠','🤡','🤥','🤫','🤭','🧐','🤓','😈','👿','👹','👺','💀','👻','👽','🤖','💩','😺','😸','😹','😻','😼','😽','🙀','😿','😾','🤲','👐','🤝','👍','👎','👊','✊','🤛','🤜','🤞','✌️','🤟','🤘','👈','👉','👆','👇','☝️','✋','🤚','🖐','🖖','👋','🤙','💪','🖕','✍️','🙏','💍','💄','💋','👄','👅','👂','👃','👣','👁','👀','🧠','🗣','👤','👥'],
+		emoji: ['😂','💯','❤️','🙌','👏','👌','😍','😯','😢','😅','😁','🙂','😎','😀','🤣','😃','😄','😆','😉','😊','😋','😘','😗','😙','😚','🤗','🤩','🤔','🤨','😐','😑','😶','🙄','😏','😣','😥','😮','🤐','😪','😫','😴','😌','😛','😜','😝','🤤','😒','😓','😔','😕','🙃','🤑','😲','🙁','😖','😞','😟','😤','😭','😦','😧','😨','😩','🤯','😬','😰','😱','😳','🤪','😵','😡','😠','🤬','😷','🤒','🤕','🤢','🤮','🤧','😇','🤠','🤡','🤥','🤫','🤭','🧐','🤓','😈','👿','👹','👺','💀','👻','👽','🤖','💩','😺','😸','😹','😻','😼','😽','🙀','😿','😾','🤲','👐','🤝','👍','👎','👊','✊','🤛','🤜','🤞','✌️','🤟','🤘','👈','👉','👆','👇','☝️','✋','🤚','🖐','🖖','👋','🤙','💪','🖕','✍️','🙏','💍','💄','💋','👄','👅','👂','👃','👣','👁','👀','🧠','🗣','👤','👥'
+		],
 };

+ 54 - 5
resources/assets/js/components/CollectionComponent.vue

@@ -15,7 +15,14 @@
 					</p>
 					<p v-if="owner == true" class="pt-3 text-center">
 						<span>
-							<button class="btn btn-outline-light btn-sm" @click.prevent="addToCollection">Add Photo</button>
+							<button class="btn btn-outline-light btn-sm" @click.prevent="addToCollection">
+								<span v-if="loadingPostList == false">Add Photo</span>
+								<span v-else class="px-4">
+									<div class="spinner-border spinner-border-sm" role="status">
+									  <span class="sr-only">Loading...</span>
+									</div>
+								</span>
+							</button>
 							 &nbsp; &nbsp; 
 							<button class="btn btn-outline-light btn-sm" @click.prevent="editCollection">Edit</button>
 							 &nbsp; &nbsp; 
@@ -62,7 +69,20 @@
 			<button type="button" class="btn btn-primary btn-sm py-1 font-weight-bold px-3 float-right" @click.prevent="updateCollection">Save</button>
 		</form>
 	</b-modal>
-	<b-modal ref="addPhotoModal" id="add-photo-modal" hide-footer centered title="Add Photo" body-class="">
+	<b-modal ref="addPhotoModal" id="add-photo-modal" hide-footer centered title="Add Photo" body-class="m-3">
+		<div class="form-group">
+			<label for="title" class="font-weight-bold text-muted">Add Recent Post</label>
+			<div class="row m-1" v-if="postsList.length > 0">
+				<div v-for="(p, index) in postsList" :key="'postList-'+index" class="col-4 p-1 cursor-pointer">
+					<div class="square">
+						<div class="square-content" v-bind:style="'background-image: url(' + p.media_attachments[0].url + ');'"></div>
+					</div>
+				</div>
+				<div class="col-12">
+					<hr>
+				</div>
+			</div>
+		</div>
 		<form>
 			<div class="form-group">
 				<label for="title" class="font-weight-bold text-muted">Add Post by URL</label>
@@ -105,12 +125,15 @@ export default {
 		return {
 			loaded: false,
 			posts: [],
+			ids: [],
 			currentUser: false,
 			owner: false,
 			title: this.collectionTitle,
 			description: this.collectionDescription,
 			visibility: this.collectionVisibility,
-			photoId: ''
+			photoId: '',
+			postsList: [],
+			loadingPostList: false
 		}
 	},
 
@@ -135,6 +158,9 @@ export default {
 			axios.get('/api/local/collection/items/' + this.collectionId)
 			.then(res => {
 				this.posts = res.data;
+				this.ids = this.posts.map(p => {
+					return p.id;
+				});
 				this.loaded = true;
 			});
 		},
@@ -149,11 +175,34 @@ export default {
 		},
 
 		addToCollection() {
-			this.$refs.addPhotoModal.show();
+			let self = this;
+			this.loadingPostList = true;
+			if(this.postsList.length == 0) {
+				axios.get('/api/pixelfed/v1/accounts/'+this.profileId+'/statuses', {
+					params: {
+						min_id: 1,
+						limit: 13
+					}
+				})
+				.then(res => {
+					self.postsList = res.data.filter(l => {
+						return self.ids.indexOf(l.id) == -1;
+					}).splice(0,9);
+					self.loadingPostList = false;
+					self.$refs.addPhotoModal.show();
+				}).catch(err => {
+					self.loadingPostList = false;
+					swal('An Error Occured', 'We cannot process your request at this time, please try again later.', 'error');
+				})
+			} else {
+				this.$refs.addPhotoModal.show();
+				this.loadingPostList = false;
+			}
 		},
 
 		pushId() {
 			let max = 18;
+			let self = this;
 			if(this.posts.length >= max) {
 				swal('Error', 'You can only add ' + max + ' posts per collection', 'error');
 				return;
@@ -174,7 +223,7 @@ export default {
 				collection_id: this.collectionId,
 				post_id: split[5]
 			}).then(res => {
-				location.reload();
+				self.ids.push(...split[5]);
 			}).catch(err => {
 				swal('Invalid URL', 'The post you entered was invalid', 'error');
 				this.photoId = '';

+ 18 - 2
resources/assets/js/components/Profile.vue

@@ -164,7 +164,7 @@
 				<div class="profile-timeline mt-md-4">
 					<div class="row" v-if="mode == 'grid'">
 						<div class="col-4 p-1 p-md-3" v-for="(s, index) in timeline">
-							<a class="card info-overlay card-md-border-0" :href="s.url">
+							<a class="card info-overlay card-md-border-0" :href="statusUrl(s)">
 								<div :class="[s.sensitive ? 'square' : 'square ' + s.media_attachments[0].filter_class]">
 									<span v-if="s.pf_type == 'photo:album'" class="float-right mr-3 post-icon"><i class="fas fa-images fa-2x"></i></span>
 									<span v-if="s.pf_type == 'video'" class="float-right mr-3 post-icon"><i class="fas fa-video fa-2x"></i></span>
@@ -329,7 +329,7 @@
 						  :gutter="{default: '5px'}"
 						>
 							<div class="p-1" v-for="(s, index) in timeline">
-								<a :class="[s.sensitive ? 'card info-overlay card-md-border-0' : s.media_attachments[0].filter_class + ' card info-overlay card-md-border-0']" :href="s.url">
+								<a :class="[s.sensitive ? 'card info-overlay card-md-border-0' : s.media_attachments[0].filter_class + ' card info-overlay card-md-border-0']" :href="statusUrl(s)">
 									<img :src="previewUrl(s)" class="img-fluid w-100">
 								</a>
 							</div>
@@ -1080,6 +1080,22 @@
 
 			formatCount(count) {
 				return App.util.format.count(count);
+			},
+
+			statusUrl(status) {
+				if(status.local == true) {
+					return status.url;
+				}
+
+				return '/i/web/post/_/' + status.account.id + '/' + status.id;
+			},
+
+			profileUrl(status) {
+				if(status.local == true) {
+					return status.account.url;
+				}
+
+				return '/i/web/profile/_/' + status.account.id;
 			}
 		}
 	}

+ 65 - 15
resources/assets/js/components/Timeline.vue

@@ -2,6 +2,7 @@
 <div class="container" style="">
 	<div class="row">
 		<div :class="[modes.distractionFree ? 'col-md-8 col-lg-8 offset-md-2 px-0 my-sm-3 timeline order-2 order-md-1':'col-md-8 col-lg-8 px-0 my-sm-3 timeline order-2 order-md-1']">
+			<div class="d-none" data-id="StoryTimelineComponent"></div>
 			<div style="padding-top:10px;">
 				<div v-if="loading" class="text-center">
 					<div class="spinner-border" role="status">
@@ -69,11 +70,11 @@
 
 					<div class="card mb-sm-4 status-card card-md-rounded-0 shadow-none border">
 						<div v-if="!modes.distractionFree" 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;">
+							<img v-bind:src="status.account.avatar" width="32px" height="32px" class="cursor-pointer" style="border-radius: 32px;" @click="profileUrl(status)">
 							<div class="pl-2">
 								<!-- <a class="d-block username font-weight-bold text-dark" v-bind:href="status.account.url" style="line-height:0.5;"> -->
-								<a class="username font-weight-bold text-dark text-decoration-none" v-bind:href="status.account.url">
-									{{status.account.username}}
+								<a class="username font-weight-bold text-dark text-decoration-none" v-bind:href="profileUrl(status)" v-html="statusCardUsernameFormat(status)">
+									Loading...
 								</a>
 								<span v-if="status.account.is_admin" class="fa-stack" title="Admin Account" data-toggle="tooltip" style="height:1em; line-height:1em; max-width:19px;">
 									<i class="fas fa-certificate text-danger fa-stack-1x"></i>
@@ -158,7 +159,7 @@
 								<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 text-lighter cursor-pointer']" title="Like" v-on:click="likeStatus(status, $event)"></h3>
 								<h3 v-if="!status.comments_disabled" class="far fa-comment text-lighter pr-3 m-0 cursor-pointer" title="Comment" v-on:click="commentFocus(status, $event)"></h3>
 								<h3 v-if="status.visibility == 'public'" v-bind:class="[status.reblogged ? 'fas fa-retweet pr-3 m-0 text-primary cursor-pointer' : 'fas fa-retweet pr-3 m-0 text-lighter share-btn cursor-pointer']" title="Share" v-on:click="shareStatus(status, $event)"></h3>
-								<span class="float-right">
+								<span v-if="status.pf_type == 'photo'" class="float-right">
 									<h3 class="fas fa-expand pr-3 m-0 cursor-pointer text-lighter" v-on:click="lightbox(status)"></h3>
 								</span>
 							</div>
@@ -169,15 +170,15 @@
 							<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>
+										<bdi><a class="text-dark" :href="profileUrl(status)">{{status.account.username}}</a></bdi>
 									</span>
-									<span v-html="status.content"></span>
+									<span class="status-content" 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>
+											<a class="text-dark font-weight-bold mr-1" :href="profileUrl(reply)">{{reply.account.username}}</a>
 											<span v-html="reply.content"></span>
 										</span>
 										<span class="mb-0" style="min-width:38px">
@@ -191,7 +192,7 @@
 							</div>
 							<div class="timestamp mt-2">
 								<p class="small text-uppercase mb-0">
-									<a :href="status.url" class="text-muted">
+									<a :href="statusUrl(status)" 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>
 									<a v-if="modes.distractionFree" class="float-right" :href="status.url">
@@ -467,7 +468,6 @@
 				profile: {},
 				min_id: 0,
 				max_id: 0,
-				stories: {},
 				suggestions: {},
 				loading: true,
 				replies: [],
@@ -579,7 +579,7 @@
 				axios.get(apiUrl, {
 					params: {
 						max_id: this.max_id,
-						limit: 5
+						limit: 3
 					}
 				}).then(res => {
 					let data = res.data;
@@ -596,6 +596,7 @@
 					if(this.hashtagPosts.length == 0) {
 						this.fetchHashtagPosts();
 					}
+					// this.fetchStories();
 				}).catch(err => {
 					swal(
 						'Oops, something went wrong',
@@ -1159,14 +1160,14 @@
 					if(tags.length == 0) {
 						return;
 					}
-					let hashtag = tags[0];
+					let hashtag = tags[Math.floor(Math.random(), tags.length)];
 					this.hashtagPostsName = hashtag;
 					axios.get('/api/v2/discover/tag', {
 						params: {
 							hashtag: hashtag
 						}
 					}).then(res => {
-						if(res.data.tags.length) {
+						if(res.data.tags.length > 3) {
 							this.showHashtagPosts = true;
 							this.hashtagPosts = res.data.tags.splice(0,3);
 						}
@@ -1210,7 +1211,7 @@
 
 			ctxMenuGoToPost() {
 				let status = this.ctxMenuStatus;
-				window.location.href = status.url;
+				window.location.href = this.statusUrl(status);
 				this.closeCtxMenu();
 				return;
 			},
@@ -1302,8 +1303,57 @@
 
 			formatCount(count) {
 				return App.util.format.count(count);
-			}
+			},
+
+			statusUrl(status) {
+				return status.url;
+
+				// if(status.local == true) {
+				// 	return status.url;
+				// }
+
+				// return '/i/web/post/_/' + status.account.id + '/' + status.id;
+			},
+
+			profileUrl(status) {
+				return status.account.url;
+				// if(status.local == true) {
+				// 	return status.account.url;
+				// }
+
+				// return '/i/web/profile/_/' + status.account.id;
+			},
+
+			statusCardUsernameFormat(status) {
+				if(status.account.local == true) {
+					return status.account.username;
+				}
 
+				let fmt = window.App.config.username.remote.format;
+				let txt = window.App.config.username.remote.custom;
+				let usr = status.account.username;
+				let dom = document.createElement('a');
+				dom.href = status.account.url;
+				dom = dom.hostname;
+
+				switch(fmt) {
+					case '@':
+						return usr + '<span class="text-lighter font-weight-bold">@' + dom + '</span>';
+					break;
+
+					case 'from':
+						return usr + '<span class="text-lighter font-weight-bold"> <span class="font-weight-normal">from</span> ' + dom + '</span>';
+					break;
+
+					case 'custom':
+						return usr + '<span class="text-lighter font-weight-bold"> ' + txt + ' ' + dom + '</span>';
+					break;
+
+					default: 
+						return usr + '<span class="text-lighter font-weight-bold">@' + dom + '</span>';
+					break;
+				}
+			},
 		}
 	}
-</script>
+</script>

+ 0 - 32
resources/assets/js/components/presenter/PhotoAlbumPresenter.vue

@@ -5,22 +5,6 @@
 				<p class="mb-0 lead font-weight-bold">{{ status.spoiler_text ? status.spoiler_text : 'CW / NSFW / Hidden Media'}}</p>
 				<p class="font-weight-light">(click to show)</p>
 			</summary>
-			<!-- <b-carousel :id="status.id + '-carousel'"
-				v-model="cursor"
-				style="text-shadow: 1px 1px 2px #333;min-height: 330px;display: flex;align-items: center;"
-				controls
-				background="#ffffff"
-				:interval="0"
-			>
-				<b-carousel-slide v-for="(img, index) in status.media_attachments" :key="img.id">
-					<div slot="img" class="d-block mx-auto text-center" style="max-height: 600px;" :title="img.description">
-						<img :class="img.filter_class + ' img-fluid'" style="max-height: 600px;" :src="img.url" :alt="img.description" loading="lazy">
-					</div>
-				</b-carousel-slide>
-				<span class="badge badge-dark box-shadow" style="position: absolute;top:10px;right:10px;">
-					{{cursor + 1}} / {{status.media_attachments.length}}
-				</span>
-			</b-carousel> -->
 			<carousel ref="carousel" :centerMode="true" :loop="false" :per-page="1" :paginationPosition="'bottom-overlay'" paginationActiveColor="#3897f0" paginationColor="#dbdbdb">
 				<slide v-for="(img, index) in status.media_attachments" :key="'px-carousel-'+img.id + '-' + index" class="w-100 h-100 d-block mx-auto text-center" :title="img.description">
 					<img :class="img.filter_class + ' img-fluid'" :src="img.url" :alt="img.description">
@@ -29,22 +13,6 @@
 		</details>
 	</div>
 	<div v-else class="w-100 h-100 p-0">
-		<!-- <b-carousel :id="status.id + '-carousel'"
-			v-model="cursor"
-			style="text-shadow: 1px 1px 2px #333;min-height: 330px;display: flex;align-items: center;"
-			controls
-			background="#ffffff"
-			:interval="0"
-		>
-			<b-carousel-slide v-for="(img, index) in status.media_attachments" :key="img.id" :title="img.description">
-				<div slot="img" class="d-block mx-auto text-center" style="max-height: 600px;">
-					<img :class="img.filter_class + ' img-fluid'" style="max-height: 600px;" :src="img.url" loading="lazy" :alt="img.description">
-				</div>
-			</b-carousel-slide>
-			<span class="badge badge-dark box-shadow" style="position: absolute;top:10px;right:10px;">
-				{{cursor + 1}} / {{status.media_attachments.length}}
-			</span>
-		</b-carousel> -->
 		<carousel ref="carousel" :centerMode="true" :loop="false" :per-page="1" :paginationPosition="'bottom-overlay'" paginationActiveColor="#3897f0" paginationColor="#dbdbdb" class="p-0 m-0">
 			<slide v-for="(img, index) in status.media_attachments" :key="'px-carousel-'+img.id + '-' + index" class="" style="background: #000; display: flex;align-items: center;" :title="img.description">
 				<img :class="img.filter_class + ' img-fluid w-100 p-0'" style="" :src="img.url" :alt="img.description">

+ 15 - 2
resources/assets/js/components/presenter/VideoPresenter.vue

@@ -6,14 +6,14 @@
 				<p class="font-weight-light">(click to show)</p>
 			</summary>
 			<div class="embed-responsive embed-responsive-1by1">
-				<video class="video" preload="none" controls loop :poster="status.media_attachments[0].preview_url">
+				<video class="video" preload="none" loop :poster="status.media_attachments[0].preview_url":data-id="status.id" @click="playOrPause($event)">
 					<source :src="status.media_attachments[0].url" :type="status.media_attachments[0].mime">
 				</video>
 			</div>
 		</details>
 	</div>
 	<div v-else class="embed-responsive embed-responsive-16by9">
-		<video class="video" preload="auto" controls loop :poster="status.media_attachments[0].preview_url">
+		<video class="video" controls preload="metadata" loop :poster="status.media_attachments[0].preview_url" :data-id="status.id">
 			<source :src="status.media_attachments[0].url" :type="status.media_attachments[0].mime">
 		</video>
 	</div>
@@ -22,5 +22,18 @@
 <script type="text/javascript">
 	export default {
 		props: ['status'],
+
+		methods: {
+			playOrPause(e) {
+				let el = e.target;
+				if(el.getAttribute('playing') == 1) {
+					el.removeAttribute('playing');
+					el.pause();
+				} else {
+					el.setAttribute('playing', 1);
+					el.play();
+				}
+			}
+		}
 	}
 </script>

+ 0 - 4
resources/assets/sass/app.scss

@@ -21,8 +21,4 @@
 
 @import '~bootstrap-vue/dist/bootstrap-vue.css';
 
-@import '~plyr/dist/plyr.css';
-
-@import '~vue-loading-overlay/dist/vue-loading.css';
-
 @import "moment";

+ 0 - 4
resources/assets/sass/appdark.scss

@@ -72,10 +72,6 @@ textarea {
 
 @import '~bootstrap-vue/dist/bootstrap-vue.css';
 
-@import '~plyr/dist/plyr.css';
-
-@import '~vue-loading-overlay/dist/vue-loading.css';
-
 @import "moment";
 
 .border {

+ 4 - 0
resources/assets/sass/custom.scss

@@ -565,4 +565,8 @@ details summary::-webkit-details-marker {
 .VueCarousel-dot:focus,
 .VueCarousel-dot--active:focus {
   outline: 0px !important;
+}
+
+.status-content > p:first-child {
+    display: inline;
 }

+ 1 - 1
resources/lang/de/auth.php

@@ -14,6 +14,6 @@ return [
     */
 
     'failed'   => 'Diese Anmeldeinformationen stimmen nicht mit unseren Daten überein.',
-    'throttle' => 'Zu viele Login-Versuche. Versuche es in :seconds Sekunden erneut.',
+    'throttle' => 'Zu viele Anmeldeversuche. Versuche es in :seconds Sekunden erneut.',
 
 ];

+ 1 - 1
resources/lang/de/helpcenter.php

@@ -15,7 +15,7 @@ return [
 	'timelines' => 'Timelines',
 	'embed'	=> 'Einbetten',
 
-	'communityGuidelines' => 'Community-Richtlinien',
+	'communityGuidelines' => 'Gemeinschaftsrichtlinien',
 	'whatIsTheFediverse' => 'Was ist das Fediversum?',
 	'controllingVisibility' => 'Sichtbarkeit steuern',
 	'blockingAccounts' => 'Kontosperrung',

+ 3 - 3
resources/lang/de/notification.php

@@ -2,11 +2,11 @@
 
 return [
 
-  'likedPhoto'          => 'gefällt dein Foto.',
+  'likedPhoto'          => 'gefällt dein Beitrag.',
   'likedComment'        => 'gefällt dein Kommentar.',
   'startedFollowingYou' => 'folgt dir nun.',
-  'commented'           => 'hat deinen Post kommentiert.',
+  'commented'           => 'hat deinen Beitrag kommentiert.',
   'mentionedYou'        => 'hat dich erwähnt.',
-  'shared'              => 'hat deinen Post teilen.',
+  'shared'              => 'hat deinen Beitrag geteilt.',
 
 ];

+ 3 - 3
resources/lang/de/passwords.php

@@ -15,8 +15,8 @@ return [
 
     'password' => 'Passwörter müssen mindestens 6 Zeichen lang sein und mit der Bestätigung übereinstimmen.',
     'reset'    => 'Dein Passwort wurde zurückgesetzt!',
-    'sent'     => 'Wir haben dir eine E-Mail zum Zurücksetzen deines Passworts gesendet!',
-    'token'    => 'Dieser Passwort-Reset-Code ist ungültig.',
-    'user'     => 'Wir konnten keinen Nutzer mit dieser E-Mail-Adresse finden.',
+    'sent'     => 'Wenn deine E-Mail-Adresse in unserer Datenbank existiert, wirst du in ein paar Minuten einen Link zum Zurücksetzen deines Passworts zugesendet bekommen. Bitte prüfe deinen Spam-Ordner, wenn du diese E-Mail nicht bekommst.',
+    'token'    => 'Dieser Code zum Passwort zurücksetzen ist ungültig.',
+    'user'     => 'Wenn deine E-Mail-Adresse in unserer Datenbank existiert, wirst du in ein paar Minuten einen Link zum Zurücksetzen deines Passworts zugesendet bekommen. Bitte prüfe deinen Spam-Ordner, wenn du diese E-Mail nicht bekommst.',
 
 ];

+ 5 - 5
resources/lang/de/profile.php

@@ -1,15 +1,15 @@
 <?php
 
 return [
-  'emptyTimeline'         => 'Dieser Benutzer hat noch nichts gepostet!',
+  'emptyTimeline'         => 'Dieser Benutzer hat noch nichts beigetragen!',
   'emptyFollowers'        => 'Diesem Benutzer folgt noch niemand!',
   'emptyFollowing'        => 'Dieser Benutzer folgt noch niemanden!',
-  'emptySaved'            => 'Du hast noch keinen Post gespeichert!',
-  'savedWarning'          => 'Nur du kannst sehen was du gespeichert hast',
-  'privateProfileWarning' => 'Dieser Account ist privat',
+  'emptySaved'            => 'Du hast noch keinen Beitrag gespeichert!',
+  'savedWarning'          => 'Nur du kannst sehen, was du gespeichert hast',
+  'privateProfileWarning' => 'Dieses Konto ist privat',
   'alreadyFollow'         => ':username bereits folgen?',
   'loginToSeeProfile'     => 'um deren Bilder und Videos zu sehen.',
 
   'status.disabled.header' 	  => 'Profil nicht verfügbar',
-  'status.disabled.body'	  => 'Entschuldigung, dieses Profil ist im Moment nicht verfügbar. Bitte versuchen Sie es später noch einmal.',
+  'status.disabled.body'	  => 'Entschuldigung, dieses Profil ist im Moment nicht verfügbar. Bitte versuche es in Kürze noch einmal.',
 ];

+ 2 - 2
resources/lang/de/site.php

@@ -8,12 +8,12 @@ return [
 	'fediverse'		=> 'Fediverse',
 	'opensource'	=> 'Open Source',
 	'terms'			=> 'Nutzungshinweise',
-	'privacy'		=> 'Privacy',
+	'privacy'		=> 'Datenschutz',
 	'l10nWip'		=> 'Wir arbeiten noch an der Unterstützung weiterer Sprachen',
 	'currentLocale' => 'Aktuelle Sprache',
 	'selectLocale'  => 'Wähle eine der unterstützten Sprachen aus',
 	'contact'		=> 'Kontakt',
 	'contact-us'	=> 'Kontaktiere uns',
-	'places'		=> 'Plätze',
+	'places'		=> 'Orte',
 
 ];

+ 46 - 6
resources/views/layouts/app.blade.php

@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+@auth
 <html lang="{{ app()->getLocale() }}">
 <head>
     <meta charset="utf-8">
@@ -8,7 +9,7 @@
 
     <meta name="mobile-web-app-capable" content="yes">
 
-    <title>{{ $title ?? config('app.name', 'Laravel') }}</title>
+    <title>{{ $title ?? config('app.name', 'Pixelfed') }}</title>
     <link rel="manifest" href="/manifest.json">
 
     <meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
@@ -36,11 +37,10 @@
     <script type="text/javascript">window.App = {config: {!!App\Util\Site\Config::json()!!}};</script>
     
 </head>
-<body class="{{Auth::check()?'loggedIn':''}}">
+<body class="loggedIn">
     @include('layouts.partial.nav')
     <main id="content">
         @yield('content')
-        @if(Auth::check())
         <div class="modal pr-0" tabindex="-1" role="dialog" id="composeModal">
           <div class="modal-dialog" role="document">
             <div class="modal-content">
@@ -48,7 +48,6 @@
             </div>
           </div>
         </div>
-        @endif
     </main>
     @include('layouts.partial.footer')
     <script type="text/javascript" src="{{ mix('js/manifest.js') }}"></script>
@@ -56,7 +55,6 @@
     <script type="text/javascript" src="{{ mix('js/app.js') }}"></script>
     <script type="text/javascript" src="{{ mix('js/components.js') }}"></script>
     @stack('scripts')
-    @if(Auth::check())
     <div class="d-block d-sm-none mt-5"></div>
     <div class="d-block d-sm-none fixed-bottom">
         <div class="card card-body rounded-0 py-2 d-flex align-items-middle box-shadow" style="border-top:1px solid #F1F5F8">
@@ -79,6 +77,48 @@
             </ul>
         </div>
     </div>
-    @endif
 </body>
 </html>
+@endauth
+
+@guest
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="mobile-web-app-capable" content="yes">
+
+    <title>{{ $title ?? config('app.name', 'Pixelfed') }}</title>
+    <link rel="manifest" href="/manifest.json">
+
+    <meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}">
+    <meta property="og:title" content="{{ $title ?? config('app.name', 'pixelfed') }}">
+    <meta property="og:type" content="article">
+    <meta property="og:url" content="{{request()->url()}}">
+    @stack('meta')
+
+    <meta name="medium" content="image">
+    <meta name="theme-color" content="#10c5f8">
+    <meta name="apple-mobile-web-app-capable" content="yes">
+    <link rel="shortcut icon" type="image/png" href="/img/favicon.png?v=2">
+    <link rel="apple-touch-icon" type="image/png" href="/img/favicon.png?v=2">
+    <link rel="canonical" href="{{request()->url()}}">
+    <link href="{{ mix('css/app.css') }}" rel="stylesheet" data-stylesheet="light">
+    
+    @stack('styles')
+</head>
+<body>
+    @include('layouts.partial.nav')
+    <main id="content">
+        @yield('content')
+    </main>
+    @include('layouts.partial.footer')
+    <script type="text/javascript" src="{{ mix('js/manifest.js') }}"></script>
+    <script type="text/javascript" src="{{ mix('js/vendor.js') }}"></script>
+    <script type="text/javascript" src="{{ mix('js/app.js') }}"></script>
+    <script type="text/javascript" src="{{ mix('js/components.js') }}"></script>
+    @stack('scripts')
+</body>
+</html>
+@endguest

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

@@ -33,9 +33,9 @@
       <li class="nav-item pl-3 {{request()->is('settings/security*')?'active':''}}">
         <a class="nav-link font-weight-light text-muted" href="{{route('settings.security')}}">Security</a>
       </li>
-      <li class="nav-item pl-3 {{request()->is('settings/sponsor*')?'active':''}}">
+      {{-- <li class="nav-item pl-3 {{request()->is('settings/sponsor*')?'active':''}}">
         <a class="nav-link font-weight-light text-muted" href="{{route('settings.sponsor')}}">Sponsor</a>
-      </li>
+      </li> --}}
       <li class="nav-item">
         <hr>
       </li>

+ 4 - 1
resources/views/status/show.blade.php

@@ -17,9 +17,12 @@
 @push('meta')
 
     <meta property="og:description" content="{{ $status->caption }}">
-    <meta property="og:image" content="{{$status->mediaUrl()}}">
+    <meta property="og:image" content="{{$status->thumb()}}">
     <link href='{{$status->url()}}' rel='alternate' type='application/activity+json'>
     <meta name="twitter:card" content="summary_large_image">
+    @if($status->viewType() == "video" || $status->viewType() == "video:album")
+        <meta property="og:video" content="{{$status->mediaUrl()}}">
+    @endif
 @endpush
 
 @push('scripts')

+ 1 - 1
routes/api.php

@@ -60,7 +60,7 @@ Route::group(['prefix' => 'api'], function() use($middleware) {
 		Route::post('statuses/{id}/unreblog', 'Api\ApiV1Controller@statusUnshare')->middleware($middleware);
 		Route::delete('statuses/{id}', 'Api\ApiV1Controller@statusDelete')->middleware($middleware);
 		Route::get('statuses/{id}', 'Api\ApiV1Controller@statusById')->middleware($middleware);
-		Route::post('statuses', 'Api\ApiV1Controller@statusCreate')->middleware($middleware);
+		Route::post('statuses', 'Api\ApiV1Controller@statusCreate')->middleware($middleware)->middleware('throttle:maxPostsPerHour,60')->middleware('throttle:maxPostsPerDay,1440');
 
 
 		Route::get('timelines/home', 'Api\ApiV1Controller@timelineHome')->middleware($middleware);

+ 3 - 3
routes/web.php

@@ -149,7 +149,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
             Route::get('exp/rec', 'ApiController@userRecommendations');
             Route::post('discover/tag/subscribe', 'HashtagFollowController@store')->middleware('throttle:maxHashtagFollowsPerHour,60')->middleware('throttle:maxHashtagFollowsPerDay,1440');;
             Route::get('discover/tag/list', 'HashtagFollowController@getTags');
-            Route::get('profile/sponsor/{id}', 'ProfileSponsorController@get');
+            // Route::get('profile/sponsor/{id}', 'ProfileSponsorController@get');
             Route::get('bookmarks', 'InternalApiController@bookmarks');
             Route::get('collection/items/{id}', 'CollectionController@getItems');
             Route::post('collection/item', 'CollectionController@storeId');
@@ -318,8 +318,8 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact
         Route::get('invites/create', 'UserInviteController@create')->name('settings.invites.create');
         Route::post('invites/create', 'UserInviteController@store');
         Route::get('invites', 'UserInviteController@show')->name('settings.invites');
-        Route::get('sponsor', 'SettingsController@sponsor')->name('settings.sponsor');
-        Route::post('sponsor', 'SettingsController@sponsorStore');
+        // Route::get('sponsor', 'SettingsController@sponsor')->name('settings.sponsor');
+        // Route::post('sponsor', 'SettingsController@sponsorStore');
     });
 
     Route::group(['prefix' => 'site'], function () {

+ 1 - 14
tests/Feature/LoginTest.php

@@ -5,6 +5,7 @@ namespace Tests\Feature;
 use Tests\TestCase;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Foundation\Testing\WithoutMiddleware;
+use App\User;
 
 class LoginTest extends TestCase
 {
@@ -16,18 +17,4 @@ class LoginTest extends TestCase
 
         $response->assertSee('Forgot Password');
     }
-
-    /** @test */
-    public function view_register_page()
-    {
-        if(true == config('pixelfed.open_registration')) {
-            $response = $this->get('register');
-
-            $response->assertSee('Register a new account');
-        } else {
-            $response = $this->get('register');
-
-            $response->assertSee('Registration is closed');
-        }
-    }
 }

部分文件因为文件数量过多而无法显示