1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/pixelfed_ynh.git synced 2024-09-03 20:06:04 +02:00

Merge pull request #1807 from pixelfed/staging

Staging
This commit is contained in:
daniel 2019-11-10 19:55:49 -07:00 committed by GitHub
commit 3b52f809f9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
49 changed files with 1079 additions and 602 deletions

View file

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

View file

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

View file

@ -10,6 +10,11 @@ Remember, bug reports are created in the hope that others with the same problem
## Core Development Discussion ## 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. 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 ## 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. 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.

View file

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

View file

@ -27,7 +27,7 @@ class AuthServiceProvider extends ServiceProvider
$this->registerPolicies(); $this->registerPolicies();
if(config('pixelfed.oauth_enabled')) { 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::tokensExpireIn(now()->addDays(15));
Passport::refreshTokensExpireIn(now()->addDays(30)); Passport::refreshTokensExpireIn(now()->addDays(30));
Passport::enableImplicitGrant(); Passport::enableImplicitGrant();

View file

@ -4,9 +4,26 @@ namespace App;
use Auth; use Auth;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Pixelfed\Snowflake\HasSnowflakePrimary;
class Story extends Model 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']; protected $visible = ['id'];
public function profile() public function profile()

View file

@ -3,10 +3,29 @@
namespace App; namespace App;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Pixelfed\Snowflake\HasSnowflakePrimary;
use Storage; use Storage;
class StoryItem extends Model 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() public function story()
{ {
return $this->belongsTo(Story::class); return $this->belongsTo(Story::class);
@ -14,6 +33,6 @@ class StoryItem extends Model
public function url() public function url()
{ {
return Storage::url($this->media_path); return url(Storage::url($this->media_path));
} }
} }

View file

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

View file

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

View file

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

View file

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

1176
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -39,5 +39,11 @@ return [
'body' => env('PAGE_503_BODY', 'Our service is in maintenance mode, please try again later.') '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)
]
],
]; ];

View file

@ -8,7 +8,7 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends git gosu \ && 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 \ 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 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 \ && sed -i '/en_US/s/^#//g' /etc/locale.gen \
&& locale-gen && update-locale \ && locale-gen && update-locale \
&& docker-php-source extract \ && docker-php-source extract \

View file

@ -8,7 +8,7 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends git gosu \ && 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 \ 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 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 \ && sed -i '/en_US/s/^#//g' /etc/locale.gen \
&& locale-gen && update-locale \ && locale-gen && update-locale \
&& docker-php-source extract \ && docker-php-source extract \

View file

@ -30,6 +30,7 @@ server {
location ~ \.php$ { location ~ \.php$ {
fastcgi_split_path_info ^(.+\.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_pass unix:/run/php-fpm/php-fpm.sock; # make sure this is correct
fastcgi_index index.php; fastcgi_index index.php;
include fastcgi_params; include fastcgi_params;

View file

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

5
package-lock.json generated
View file

@ -10484,6 +10484,11 @@
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" "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=="
} }
} }
} }

View file

@ -8,8 +8,7 @@
"watch-poll": "npm run watch -- --watch-poll", "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", "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", "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", "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"
}, },
"devDependencies": { "devDependencies": {
"axios": "^0.18.1", "axios": "^0.18.1",
@ -28,21 +27,15 @@
"dependencies": { "dependencies": {
"@trevoreyre/autocomplete-vue": "^2.0.2", "@trevoreyre/autocomplete-vue": "^2.0.2",
"bootstrap-vue": "^2.0.0-rc.26", "bootstrap-vue": "^2.0.0-rc.26",
"emoji-mart-vue": "^2.6.6",
"filesize": "^3.6.1", "filesize": "^3.6.1",
"howler": "^2.1.2", "howler": "^2.1.2",
"infinite-scroll": "^3.0.6", "infinite-scroll": "^3.0.6",
"laravel-echo": "^1.5.4", "laravel-echo": "^1.5.4",
"laravel-mix": "^4.1.2", "laravel-mix": "^4.1.2",
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"opencollective": "^1.0.3",
"opencollective-postinstall": "^2.0.2",
"plyr": "^3.5.6",
"promise-polyfill": "8.1.0", "promise-polyfill": "8.1.0",
"pusher-js": "^4.4.0",
"quill": "^1.3.7", "quill": "^1.3.7",
"readmore-js": "^2.2.1", "readmore-js": "^2.2.1",
"socket.io-client": "^2.2.0",
"sweetalert": "^2.1.2", "sweetalert": "^2.1.2",
"twitter-text": "^2.0.5", "twitter-text": "^2.0.5",
"vue-carousel": "^0.18.0", "vue-carousel": "^0.18.0",
@ -50,7 +43,8 @@
"vue-cropperjs": "^4.0.0", "vue-cropperjs": "^4.0.0",
"vue-infinite-loading": "^2.4.4", "vue-infinite-loading": "^2.4.4",
"vue-loading-overlay": "^3.2.0", "vue-loading-overlay": "^3.2.0",
"vue-timeago": "^5.1.2" "vue-timeago": "^5.1.2",
"zuck.js": "^1.5.4"
}, },
"collective": { "collective": {
"type": "opencollective", "type": "opencollective",

4
public/css/app.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/app.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/status.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -3,13 +3,13 @@
"/js/vendor.js": "/js/vendor.js?id=fac92a458473b287c543", "/js/vendor.js": "/js/vendor.js?id=fac92a458473b287c543",
"/js/ace.js": "/js/ace.js?id=585114d8896dc0c24020", "/js/ace.js": "/js/ace.js?id=585114d8896dc0c24020",
"/js/activity.js": "/js/activity.js?id=713d9542e71e87fb88c0", "/js/activity.js": "/js/activity.js?id=713d9542e71e87fb88c0",
"/js/app.js": "/js/app.js?id=16017d5f3472ac2d6ee3", "/js/app.js": "/js/app.js?id=e247f50c24aaed688cc9",
"/css/app.css": "/css/app.css?id=56379e7c98ba2945e829", "/css/app.css": "/css/app.css?id=67a82ced484bdb354748",
"/css/appdark.css": "/css/appdark.css?id=83064c1642bdd3457156", "/css/appdark.css": "/css/appdark.css?id=b0fdec1caa1ce13301c6",
"/css/landing.css": "/css/landing.css?id=221a8ef5424fab0875d9", "/css/landing.css": "/css/landing.css?id=66d18d3f53fa9d41033c",
"/css/quill.css": "/css/quill.css?id=711b2150d518816d6112", "/css/quill.css": "/css/quill.css?id=711b2150d518816d6112",
"/js/collectioncompose.js": "/js/collectioncompose.js?id=b27e524d161917a9e9e1", "/js/collectioncompose.js": "/js/collectioncompose.js?id=b27e524d161917a9e9e1",
"/js/collections.js": "/js/collections.js?id=5e47d9f51d8eaddc4d24", "/js/collections.js": "/js/collections.js?id=dcc75eec0b3e0736e5fe",
"/js/components.js": "/js/components.js?id=be8c9e1c6c52db778f29", "/js/components.js": "/js/components.js?id=be8c9e1c6c52db778f29",
"/js/compose.js": "/js/compose.js?id=2d3e96bd3197d49cfe88", "/js/compose.js": "/js/compose.js?id=2d3e96bd3197d49cfe88",
"/js/compose-classic.js": "/js/compose-classic.js?id=e7483681a575c190a43b", "/js/compose-classic.js": "/js/compose-classic.js?id=e7483681a575c190a43b",
@ -18,10 +18,10 @@
"/js/hashtag.js": "/js/hashtag.js?id=3fe97ed3f975f0e0baa5", "/js/hashtag.js": "/js/hashtag.js?id=3fe97ed3f975f0e0baa5",
"/js/loops.js": "/js/loops.js?id=9c31302552d789d5f35b", "/js/loops.js": "/js/loops.js?id=9c31302552d789d5f35b",
"/js/mode-dot.js": "/js/mode-dot.js?id=993d7fee684361edddbc", "/js/mode-dot.js": "/js/mode-dot.js?id=993d7fee684361edddbc",
"/js/profile.js": "/js/profile.js?id=749e6e867d987d8d4522", "/js/profile.js": "/js/profile.js?id=97bec372a25ffd2e909e",
"/js/quill.js": "/js/quill.js?id=37962cd45a252d2f13c9", "/js/quill.js": "/js/quill.js?id=37962cd45a252d2f13c9",
"/js/search.js": "/js/search.js?id=f312959df65e86a307a3", "/js/search.js": "/js/search.js?id=f312959df65e86a307a3",
"/js/status.js": "/js/status.js?id=90bc60c7fd41b67a38db", "/js/status.js": "/js/status.js?id=dd20c64c2a1d7f3c6bce",
"/js/theme-monokai.js": "/js/theme-monokai.js?id=700e5dc735365e184e41", "/js/theme-monokai.js": "/js/theme-monokai.js?id=700e5dc735365e184e41",
"/js/timeline.js": "/js/timeline.js?id=8347abbb95fcae63ce63" "/js/timeline.js": "/js/timeline.js?id=e45ea0de04ac33768c74"
} }

View file

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

View file

@ -15,7 +15,14 @@
</p> </p>
<p v-if="owner == true" class="pt-3 text-center"> <p v-if="owner == true" class="pt-3 text-center">
<span> <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; &nbsp; &nbsp;
<button class="btn btn-outline-light btn-sm" @click.prevent="editCollection">Edit</button> <button class="btn btn-outline-light btn-sm" @click.prevent="editCollection">Edit</button>
&nbsp; &nbsp; &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> <button type="button" class="btn btn-primary btn-sm py-1 font-weight-bold px-3 float-right" @click.prevent="updateCollection">Save</button>
</form> </form>
</b-modal> </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> <form>
<div class="form-group"> <div class="form-group">
<label for="title" class="font-weight-bold text-muted">Add Post by URL</label> <label for="title" class="font-weight-bold text-muted">Add Post by URL</label>
@ -105,12 +125,15 @@ export default {
return { return {
loaded: false, loaded: false,
posts: [], posts: [],
ids: [],
currentUser: false, currentUser: false,
owner: false, owner: false,
title: this.collectionTitle, title: this.collectionTitle,
description: this.collectionDescription, description: this.collectionDescription,
visibility: this.collectionVisibility, visibility: this.collectionVisibility,
photoId: '' photoId: '',
postsList: [],
loadingPostList: false
} }
}, },
@ -135,6 +158,9 @@ export default {
axios.get('/api/local/collection/items/' + this.collectionId) axios.get('/api/local/collection/items/' + this.collectionId)
.then(res => { .then(res => {
this.posts = res.data; this.posts = res.data;
this.ids = this.posts.map(p => {
return p.id;
});
this.loaded = true; this.loaded = true;
}); });
}, },
@ -149,11 +175,34 @@ export default {
}, },
addToCollection() { 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() { pushId() {
let max = 18; let max = 18;
let self = this;
if(this.posts.length >= max) { if(this.posts.length >= max) {
swal('Error', 'You can only add ' + max + ' posts per collection', 'error'); swal('Error', 'You can only add ' + max + ' posts per collection', 'error');
return; return;
@ -174,7 +223,7 @@ export default {
collection_id: this.collectionId, collection_id: this.collectionId,
post_id: split[5] post_id: split[5]
}).then(res => { }).then(res => {
location.reload(); self.ids.push(...split[5]);
}).catch(err => { }).catch(err => {
swal('Invalid URL', 'The post you entered was invalid', 'error'); swal('Invalid URL', 'The post you entered was invalid', 'error');
this.photoId = ''; this.photoId = '';

View file

@ -164,7 +164,7 @@
<div class="profile-timeline mt-md-4"> <div class="profile-timeline mt-md-4">
<div class="row" v-if="mode == 'grid'"> <div class="row" v-if="mode == 'grid'">
<div class="col-4 p-1 p-md-3" v-for="(s, index) in timeline"> <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]"> <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 == '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> <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'}" :gutter="{default: '5px'}"
> >
<div class="p-1" v-for="(s, index) in timeline"> <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"> <img :src="previewUrl(s)" class="img-fluid w-100">
</a> </a>
</div> </div>
@ -1080,6 +1080,22 @@
formatCount(count) { formatCount(count) {
return App.util.format.count(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;
} }
} }
} }

View file

@ -2,6 +2,7 @@
<div class="container" style=""> <div class="container" style="">
<div class="row"> <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="[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 style="padding-top:10px;">
<div v-if="loading" class="text-center"> <div v-if="loading" class="text-center">
<div class="spinner-border" role="status"> <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 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"> <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"> <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="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"> <a class="username font-weight-bold text-dark text-decoration-none" v-bind:href="profileUrl(status)" v-html="statusCardUsernameFormat(status)">
{{status.account.username}} Loading...
</a> </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;"> <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> <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-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.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> <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> <h3 class="fas fa-expand pr-3 m-0 cursor-pointer text-lighter" v-on:click="lightbox(status)"></h3>
</span> </span>
</div> </div>
@ -169,15 +170,15 @@
<div class="caption"> <div class="caption">
<p class="mb-2 read-more" style="overflow: hidden;"> <p class="mb-2 read-more" style="overflow: hidden;">
<span class="username font-weight-bold"> <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>
<span v-html="status.content"></span> <span class="status-content" v-html="status.content"></span>
</p> </p>
</div> </div>
<div class="comments" v-if="status.id == replyId && !status.comments_disabled"> <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"> <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> <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 v-html="reply.content"></span>
</span> </span>
<span class="mb-0" style="min-width:38px"> <span class="mb-0" style="min-width:38px">
@ -191,7 +192,7 @@
</div> </div>
<div class="timestamp mt-2"> <div class="timestamp mt-2">
<p class="small text-uppercase mb-0"> <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> <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>
<a v-if="modes.distractionFree" class="float-right" :href="status.url"> <a v-if="modes.distractionFree" class="float-right" :href="status.url">
@ -467,7 +468,6 @@
profile: {}, profile: {},
min_id: 0, min_id: 0,
max_id: 0, max_id: 0,
stories: {},
suggestions: {}, suggestions: {},
loading: true, loading: true,
replies: [], replies: [],
@ -579,7 +579,7 @@
axios.get(apiUrl, { axios.get(apiUrl, {
params: { params: {
max_id: this.max_id, max_id: this.max_id,
limit: 5 limit: 3
} }
}).then(res => { }).then(res => {
let data = res.data; let data = res.data;
@ -596,6 +596,7 @@
if(this.hashtagPosts.length == 0) { if(this.hashtagPosts.length == 0) {
this.fetchHashtagPosts(); this.fetchHashtagPosts();
} }
// this.fetchStories();
}).catch(err => { }).catch(err => {
swal( swal(
'Oops, something went wrong', 'Oops, something went wrong',
@ -1159,14 +1160,14 @@
if(tags.length == 0) { if(tags.length == 0) {
return; return;
} }
let hashtag = tags[0]; let hashtag = tags[Math.floor(Math.random(), tags.length)];
this.hashtagPostsName = hashtag; this.hashtagPostsName = hashtag;
axios.get('/api/v2/discover/tag', { axios.get('/api/v2/discover/tag', {
params: { params: {
hashtag: hashtag hashtag: hashtag
} }
}).then(res => { }).then(res => {
if(res.data.tags.length) { if(res.data.tags.length > 3) {
this.showHashtagPosts = true; this.showHashtagPosts = true;
this.hashtagPosts = res.data.tags.splice(0,3); this.hashtagPosts = res.data.tags.splice(0,3);
} }
@ -1210,7 +1211,7 @@
ctxMenuGoToPost() { ctxMenuGoToPost() {
let status = this.ctxMenuStatus; let status = this.ctxMenuStatus;
window.location.href = status.url; window.location.href = this.statusUrl(status);
this.closeCtxMenu(); this.closeCtxMenu();
return; return;
}, },
@ -1302,8 +1303,57 @@
formatCount(count) { formatCount(count) {
return App.util.format.count(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>

View file

@ -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="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> <p class="font-weight-light">(click to show)</p>
</summary> </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"> <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"> <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"> <img :class="img.filter_class + ' img-fluid'" :src="img.url" :alt="img.description">
@ -29,22 +13,6 @@
</details> </details>
</div> </div>
<div v-else class="w-100 h-100 p-0"> <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"> <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"> <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"> <img :class="img.filter_class + ' img-fluid w-100 p-0'" style="" :src="img.url" :alt="img.description">

View file

@ -6,14 +6,14 @@
<p class="font-weight-light">(click to show)</p> <p class="font-weight-light">(click to show)</p>
</summary> </summary>
<div class="embed-responsive embed-responsive-1by1"> <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"> <source :src="status.media_attachments[0].url" :type="status.media_attachments[0].mime">
</video> </video>
</div> </div>
</details> </details>
</div> </div>
<div v-else class="embed-responsive embed-responsive-16by9"> <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"> <source :src="status.media_attachments[0].url" :type="status.media_attachments[0].mime">
</video> </video>
</div> </div>
@ -22,5 +22,18 @@
<script type="text/javascript"> <script type="text/javascript">
export default { export default {
props: ['status'], 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> </script>

View file

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

View file

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

View file

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

View file

@ -14,6 +14,6 @@ return [
*/ */
'failed' => 'Diese Anmeldeinformationen stimmen nicht mit unseren Daten überein.', '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.',
]; ];

View file

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

View file

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

View file

@ -15,8 +15,8 @@ return [
'password' => 'Passwörter müssen mindestens 6 Zeichen lang sein und mit der Bestätigung übereinstimmen.', 'password' => 'Passwörter müssen mindestens 6 Zeichen lang sein und mit der Bestätigung übereinstimmen.',
'reset' => 'Dein Passwort wurde zurückgesetzt!', 'reset' => 'Dein Passwort wurde zurückgesetzt!',
'sent' => 'Wir haben dir eine E-Mail zum Zurücksetzen deines Passworts gesendet!', '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 Passwort-Reset-Code ist ungültig.', 'token' => 'Dieser Code zum Passwort zurücksetzen ist ungültig.',
'user' => 'Wir konnten keinen Nutzer mit dieser E-Mail-Adresse finden.', '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.',
]; ];

View file

@ -1,15 +1,15 @@
<?php <?php
return [ return [
'emptyTimeline' => 'Dieser Benutzer hat noch nichts gepostet!', 'emptyTimeline' => 'Dieser Benutzer hat noch nichts beigetragen!',
'emptyFollowers' => 'Diesem Benutzer folgt noch niemand!', 'emptyFollowers' => 'Diesem Benutzer folgt noch niemand!',
'emptyFollowing' => 'Dieser Benutzer folgt noch niemanden!', 'emptyFollowing' => 'Dieser Benutzer folgt noch niemanden!',
'emptySaved' => 'Du hast noch keinen Post gespeichert!', 'emptySaved' => 'Du hast noch keinen Beitrag gespeichert!',
'savedWarning' => 'Nur du kannst sehen was du gespeichert hast', 'savedWarning' => 'Nur du kannst sehen, was du gespeichert hast',
'privateProfileWarning' => 'Dieser Account ist privat', 'privateProfileWarning' => 'Dieses Konto ist privat',
'alreadyFollow' => ':username bereits folgen?', 'alreadyFollow' => ':username bereits folgen?',
'loginToSeeProfile' => 'um deren Bilder und Videos zu sehen.', 'loginToSeeProfile' => 'um deren Bilder und Videos zu sehen.',
'status.disabled.header' => 'Profil nicht verfügbar', '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.',
]; ];

View file

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

View file

@ -1,4 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
@auth
<html lang="{{ app()->getLocale() }}"> <html lang="{{ app()->getLocale() }}">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
@ -8,7 +9,7 @@
<meta name="mobile-web-app-capable" content="yes"> <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"> <link rel="manifest" href="/manifest.json">
<meta property="og:site_name" content="{{ config('app.name', 'pixelfed') }}"> <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> <script type="text/javascript">window.App = {config: {!!App\Util\Site\Config::json()!!}};</script>
</head> </head>
<body class="{{Auth::check()?'loggedIn':''}}"> <body class="loggedIn">
@include('layouts.partial.nav') @include('layouts.partial.nav')
<main id="content"> <main id="content">
@yield('content') @yield('content')
@if(Auth::check())
<div class="modal pr-0" tabindex="-1" role="dialog" id="composeModal"> <div class="modal pr-0" tabindex="-1" role="dialog" id="composeModal">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
@ -48,7 +48,6 @@
</div> </div>
</div> </div>
</div> </div>
@endif
</main> </main>
@include('layouts.partial.footer') @include('layouts.partial.footer')
<script type="text/javascript" src="{{ mix('js/manifest.js') }}"></script> <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/app.js') }}"></script>
<script type="text/javascript" src="{{ mix('js/components.js') }}"></script> <script type="text/javascript" src="{{ mix('js/components.js') }}"></script>
@stack('scripts') @stack('scripts')
@if(Auth::check())
<div class="d-block d-sm-none mt-5"></div> <div class="d-block d-sm-none mt-5"></div>
<div class="d-block d-sm-none fixed-bottom"> <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"> <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> </ul>
</div> </div>
</div> </div>
@endif
</body> </body>
</html> </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

View file

@ -33,9 +33,9 @@
<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 font-weight-light 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 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> <a class="nav-link font-weight-light text-muted" href="{{route('settings.sponsor')}}">Sponsor</a>
</li> </li> --}}
<li class="nav-item"> <li class="nav-item">
<hr> <hr>
</li> </li>

View file

@ -17,9 +17,12 @@
@push('meta') @push('meta')
<meta property="og:description" content="{{ $status->caption }}"> <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'> <link href='{{$status->url()}}' rel='alternate' type='application/activity+json'>
<meta name="twitter:card" content="summary_large_image"> <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 @endpush
@push('scripts') @push('scripts')

View file

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

View file

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

View file

@ -5,6 +5,7 @@ namespace Tests\Feature;
use Tests\TestCase; use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware; use Illuminate\Foundation\Testing\WithoutMiddleware;
use App\User;
class LoginTest extends TestCase class LoginTest extends TestCase
{ {
@ -16,18 +17,4 @@ class LoginTest extends TestCase
$response->assertSee('Forgot Password'); $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');
}
}
} }