Merge pull request #3430 from pixelfed/staging

Staging
pull/3438/head
daniel 3 years ago committed by GitHub
commit ce7339d0f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -125,8 +125,12 @@
- Updated CollectionController, limit unpublished collections to owner. ([a0061eb5](https://github.com/pixelfed/pixelfed/commit/a0061eb5))
- Updated AP Inbox, fixes #3332. ([f8931dc7](https://github.com/pixelfed/pixelfed/commit/f8931dc7))
- Updated AdminReportController, add account delete button. ([563817a9](https://github.com/pixelfed/pixelfed/commit/563817a9))
- Updated ApiV1Controller, added /api/v2/media endpoint, fixes #3405 ([f07cc14c](https://github.com/pixelfed/pixelfed/commit/f07cc14c))
- Updated AP fanout, added Content-Type and User-Agent for activity delivery ([@noellabo](https://github.com/noellabo)) ([209c125](https://github.com/pixelfed/pixelfed/commit/209c125))
- Updated ApiV1Controller, added /api/v2/media endpoint, fixes #3405. ([f07cc14c](https://github.com/pixelfed/pixelfed/commit/f07cc14c))
- Updated AP fanout, added Content-Type and User-Agent for activity delivery. ([@noellabo](https://github.com/noellabo)) ([209c125](https://github.com/pixelfed/pixelfed/commit/209c125))
- Updated DirectMessageController to support new Metro 2.0 UI DMs. ([a4659fd2](https://github.com/pixelfed/pixelfed/commit/a4659fd2))
- Updated Like model, bump max likes per day from 100 to 200. ([71ba5fed](https://github.com/pixelfed/pixelfed/commit/71ba5fed))
- Updated HashtagService, use sorted set for followed tags. ([153eb6ba](https://github.com/pixelfed/pixelfed/commit/153eb6ba))
- Updated Discover component, fixed post side effects (fixes #3409). ([fe5a92b2](https://github.com/pixelfed/pixelfed/commit/fe5a92b2))
- ([](https://github.com/pixelfed/pixelfed/commit/))
## [v0.11.2 (2022-01-09)](https://github.com/pixelfed/pixelfed/compare/v0.11.1...v0.11.2)

@ -1061,7 +1061,7 @@ class ApiV1Controller extends Controller
abort_if(
Like::whereProfileId($user->profile_id)
->where('created_at', '>', now()->subDay())
->count() >= 100,
->count() >= Like::MAX_PER_DAY,
429
);

@ -19,6 +19,8 @@ use App\Services\MediaBlocklistService;
use App\Jobs\StatusPipeline\NewStatusPipeline;
use Illuminate\Support\Str;
use App\Util\ActivityPub\Helpers;
use App\Services\AccountService;
use App\Services\StatusService;
use App\Services\WebfingerService;
use App\Models\Conversation;
@ -435,8 +437,10 @@ class DirectMessageController extends Controller
->get();
}
$res = $res->map(function($s) use ($uid){
$res = $res->filter(function($s) {
return $s && $s->status;
})
->map(function($s) use ($uid) {
return [
'id' => (string) $s->id,
'hidden' => (bool) $s->is_hidden,
@ -449,7 +453,8 @@ class DirectMessageController extends Controller
'reportId' => (string) $s->status_id,
'meta' => json_decode($s->meta,true)
];
});
})
->values();
$w = [
'id' => (string) $r->id,
@ -458,10 +463,10 @@ class DirectMessageController extends Controller
'avatar' => $r->avatarUrl(),
'url' => $r->url(),
'muted' => UserFilter::whereUserId($uid)
->whereFilterableId($r->id)
->whereFilterableType('App\Profile')
->whereFilterType('dm.mute')
->first() ? true : false,
->whereFilterableId($r->id)
->whereFilterableType('App\Profile')
->whereFilterType('dm.mute')
->first() ? true : false,
'isLocal' => (bool) !$r->domain,
'domain' => $r->domain,
'timeAgo' => $r->created_at->diffForHumans(null, true, true),
@ -482,17 +487,62 @@ class DirectMessageController extends Controller
$pid = $request->user()->profile_id;
$dm = DirectMessage::whereFromId($pid)
->whereStatusId($sid)
->firstOrFail();
->whereStatusId($sid)
->firstOrFail();
$status = Status::whereProfileId($pid)
->findOrFail($dm->status_id);
->findOrFail($dm->status_id);
$recipient = AccountService::get($dm->to_id);
if(!$recipient) {
return response('', 422);
}
if($dm->recipient->domain) {
if($recipient['local'] == false) {
$dmc = $dm;
$this->remoteDelete($dmc);
}
if(Conversation::whereStatusId($sid)->count()) {
$latest = DirectMessage::where(['from_id' => $dm->from_id, 'to_id' => $dm->to_id])
->orWhere(['to_id' => $dm->from_id, 'from_id' => $dm->to_id])
->latest()
->first();
if($latest->status_id == $sid) {
Conversation::where(['to_id' => $dm->from_id, 'from_id' => $dm->to_id])
->update([
'updated_at' => $latest->updated_at,
'status_id' => $latest->status_id,
'type' => $latest->type,
'is_hidden' => false
]);
Conversation::where(['to_id' => $dm->to_id, 'from_id' => $dm->from_id])
->update([
'updated_at' => $latest->updated_at,
'status_id' => $latest->status_id,
'type' => $latest->type,
'is_hidden' => false
]);
} else {
Conversation::where([
'status_id' => $sid,
'to_id' => $dm->from_id,
'from_id' => $dm->to_id
])->delete();
Conversation::where([
'status_id' => $sid,
'from_id' => $dm->from_id,
'to_id' => $dm->to_id
])->delete();
}
}
StatusService::del($status->id, true);
$status->delete();
$dm->delete();

@ -16,7 +16,11 @@ use App\{
};
use Auth, DB, Cache;
use Illuminate\Http\Request;
use App\Services\BookmarkService;
use App\Services\ConfigCacheService;
use App\Services\HashtagService;
use App\Services\LikeService;
use App\Services\ReblogService;
use App\Services\StatusHashtagService;
use App\Services\SnowflakeService;
use App\Services\StatusService;
@ -76,10 +80,8 @@ class DiscoverController extends Controller
$tag = $request->input('hashtag');
$hashtag = Hashtag::whereName($tag)->firstOrFail();
if($user && $page == 1) {
$res['follows'] = HashtagFollow::whereUserId($user->id)
->whereHashtagId($hashtag->id)
->exists();
if($user) {
$res['follows'] = HashtagService::isFollowing($user->profile_id, $hashtag->id);
}
$res['hashtag'] = [
'name' => $hashtag->name,
@ -88,6 +90,12 @@ class DiscoverController extends Controller
if($user) {
$tags = StatusHashtagService::get($hashtag->id, $page, $end);
$res['tags'] = collect($tags)
->map(function($tag) use($user) {
$tag['status']['favourited'] = (bool) LikeService::liked($user->profile_id, $tag['status']['id']);
$tag['status']['reblogged'] = (bool) ReblogService::get($user->profile_id, $tag['status']['id']);
$tag['status']['bookmarked'] = (bool) BookmarkService::get($user->profile_id, $tag['status']['id']);
return $tag;
})
->filter(function($tag) {
if(!StatusService::get($tag['status']['id'])) {
return false;

@ -9,6 +9,7 @@ use App\{
HashtagFollow,
Status
};
use App\Services\HashtagService;
class HashtagFollowController extends Controller
{
@ -37,9 +38,11 @@ class HashtagFollowController extends Controller
if($hashtagFollow->wasRecentlyCreated) {
$state = 'created';
HashtagService::follow($profile->id, $hashtag->id);
// todo: send to HashtagFollowService
} else {
$state = 'deleted';
HashtagService::unfollow($profile->id, $hashtag->id);
$hashtagFollow->delete();
}

@ -33,6 +33,12 @@ class LikeController extends Controller
$like = Like::whereProfileId($profile->id)->whereStatusId($status->id)->firstOrFail();
UnlikePipeline::dispatch($like);
} else {
abort_if(
Like::whereProfileId($user->profile_id)
->where('created_at', '>', now()->subDay())
->count() >= Like::MAX_PER_DAY,
429
);
$count = $status->likes_count > 4 ? $status->likes_count : $status->likes()->count();
$like = Like::firstOrCreate([
'profile_id' => $user->profile_id,

@ -81,7 +81,6 @@ class StoryFanout implements ShouldQueue
foreach($audience as $url) {
$version = config('pixelfed.version');
$appUrl = config('app.url');
$proxy = config('');
$headers = HttpSignature::sign($profile, $url, $activity, [
'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'User-Agent' => "(Pixelfed/{$version}; +{$appUrl})",

@ -9,6 +9,8 @@ class Like extends Model
{
use SoftDeletes;
const MAX_PER_DAY = 200;
/**
* The attributes that should be mutated to dates.
*

@ -2,12 +2,16 @@
namespace App\Services;
use Cache;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;
use App\Hashtag;
use App\StatusHashtag;
use App\HashtagFollow;
class HashtagService {
const FOLLOW_KEY = 'pf:services:hashtag:following:';
public static function get($id)
{
return Cache::remember('services:hashtag:by_id:' . $id, 3600, function() use($id) {
@ -29,4 +33,35 @@ class HashtagService {
});
}
public static function isFollowing($pid, $hid)
{
$res = Redis::zscore(self::FOLLOW_KEY . $pid, $hid);
if($res) {
return true;
}
$synced = Cache::get(self::FOLLOW_KEY . $pid . ':synced');
if(!$synced) {
$tags = HashtagFollow::whereProfileId($pid)
->get()
->each(function($tag) use($pid) {
self::follow($pid, $tag->hashtag_id);
});
Cache::set(self::FOLLOW_KEY . $pid . ':synced', true, 1209600);
return (bool) Redis::zscore(self::FOLLOW_KEY . $pid, $hid) > 1;
}
return false;
}
public static function follow($pid, $hid)
{
return Redis::zadd(self::FOLLOW_KEY . $pid, $hid, $hid);
}
public static function unfollow($pid, $hid)
{
return Redis::zrem(self::FOLLOW_KEY . $pid, $hid);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
/*! @source http://purl.eligrey.com/github/canvas-toBlob.js/blob/master/canvas-toBlob.js */

@ -1 +1 @@
(()=>{"use strict";var e,r,t,s={},o={};function i(e){var r=o[e];if(void 0!==r)return r.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return s[e].call(t.exports,t,t.exports,i),t.loaded=!0,t.exports}i.m=s,e=[],i.O=(r,t,s,o)=>{if(!t){var n=1/0;for(p=0;p<e.length;p++){for(var[t,s,o]=e[p],a=!0,d=0;d<t.length;d++)(!1&o||n>=o)&&Object.keys(i.O).every((e=>i.O[e](t[d])))?t.splice(d--,1):(a=!1,o<n&&(n=o));if(a){e.splice(p--,1);var l=s();void 0!==l&&(r=l)}}return r}o=o||0;for(var p=e.length;p>0&&e[p-1][2]>o;p--)e[p]=e[p-1];e[p]=[t,s,o]},i.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return i.d(r,{a:r}),r},i.d=(e,r)=>{for(var t in r)i.o(r,t)&&!i.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((r,t)=>(i.f[t](e,r),r)),[])),i.u=e=>163===e?"js/home-0esirpejd.js":560===e?"js/compose-0esirpejd.js":483===e?"js/post-0esirpejd.js":839===e?"js/profile-0esirpejd.js":191===e?"js/dmym-0esirpejd.js":747===e?"js/dmyh-0esirpejd.js":563===e?"js/daci-0esirpejd.js":824===e?"js/dffc-0esirpejd.js":9===e?"js/dsfc-0esirpejd.js":216===e?"js/dssc-0esirpejd.js":void 0,i.miniCssF=e=>({138:"css/spa",170:"css/app",242:"css/appdark",703:"css/admin",994:"css/landing"}[e]+".css"),i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="pixelfed:",i.l=(e,s,o,n)=>{if(r[e])r[e].push(s);else{var a,d;if(void 0!==o)for(var l=document.getElementsByTagName("script"),p=0;p<l.length;p++){var c=l[p];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")==t+o){a=c;break}}a||(d=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,i.nc&&a.setAttribute("nonce",i.nc),a.setAttribute("data-webpack",t+o),a.src=e),r[e]=[s];var u=(t,s)=>{a.onerror=a.onload=null,clearTimeout(f);var o=r[e];if(delete r[e],a.parentNode&&a.parentNode.removeChild(a),o&&o.forEach((e=>e(s))),t)return t(s)},f=setTimeout(u.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=u.bind(null,a.onerror),a.onload=u.bind(null,a.onload),d&&document.head.appendChild(a)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.p="/",(()=>{var e={929:0,242:0,170:0,138:0,703:0,994:0};i.f.j=(r,t)=>{var s=i.o(e,r)?e[r]:void 0;if(0!==s)if(s)t.push(s[2]);else if(/^(138|170|242|703|929|994)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>s=e[r]=[t,o]));t.push(s[2]=o);var n=i.p+i.u(r),a=new Error;i.l(n,(t=>{if(i.o(e,r)&&(0!==(s=e[r])&&(e[r]=void 0),s)){var o=t&&("load"===t.type?"missing":t.type),n=t&&t.target&&t.target.src;a.message="Loading chunk "+r+" failed.\n("+o+": "+n+")",a.name="ChunkLoadError",a.type=o,a.request=n,s[1](a)}}),"chunk-"+r,r)}},i.O.j=r=>0===e[r];var r=(r,t)=>{var s,o,[n,a,d]=t,l=0;if(n.some((r=>0!==e[r]))){for(s in a)i.o(a,s)&&(i.m[s]=a[s]);if(d)var p=d(i)}for(r&&r(t);l<n.length;l++)o=n[l],i.o(e,o)&&e[o]&&e[o][0](),e[o]=0;return i.O(p)},t=self.webpackChunkpixelfed=self.webpackChunkpixelfed||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,r,t,n={},o={};function a(e){var r=o[e];if(void 0!==r)return r.exports;var t=o[e]={id:e,loaded:!1,exports:{}};return n[e].call(t.exports,t,t.exports,a),t.loaded=!0,t.exports}a.m=n,e=[],a.O=(r,t,n,o)=>{if(!t){var s=1/0;for(p=0;p<e.length;p++){for(var[t,n,o]=e[p],i=!0,d=0;d<t.length;d++)(!1&o||s>=o)&&Object.keys(a.O).every((e=>a.O[e](t[d])))?t.splice(d--,1):(i=!1,o<s&&(s=o));if(i){e.splice(p--,1);var l=n();void 0!==l&&(r=l)}}return r}o=o||0;for(var p=e.length;p>0&&e[p-1][2]>o;p--)e[p]=e[p-1];e[p]=[t,n,o]},a.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return a.d(r,{a:r}),r},a.d=(e,r)=>{for(var t in r)a.o(r,t)&&!a.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce(((r,t)=>(a.f[t](e,r),r)),[])),a.u=e=>299===e?"js/home-nza92p6rg.js":918===e?"js/compose-nza92p6rg.js":317===e?"js/post-nza92p6rg.js":192===e?"js/profile-nza92p6rg.js":111===e?"js/dmym-nza92p6rg.js":483===e?"js/dmyh-nza92p6rg.js":281===e?"js/daci-nza92p6rg.js":271===e?"js/dffc-nza92p6rg.js":549===e?"js/dsfc-nza92p6rg.js":565===e?"js/dssc-nza92p6rg.js":void 0,a.miniCssF=e=>({138:"css/spa",170:"css/app",242:"css/appdark",703:"css/admin",994:"css/landing"}[e]+".css"),a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),r={},t="pixelfed:",a.l=(e,n,o,s)=>{if(r[e])r[e].push(n);else{var i,d;if(void 0!==o)for(var l=document.getElementsByTagName("script"),p=0;p<l.length;p++){var c=l[p];if(c.getAttribute("src")==e||c.getAttribute("data-webpack")==t+o){i=c;break}}i||(d=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.setAttribute("data-webpack",t+o),i.src=e),r[e]=[n];var u=(t,n)=>{i.onerror=i.onload=null,clearTimeout(f);var o=r[e];if(delete r[e],i.parentNode&&i.parentNode.removeChild(i),o&&o.forEach((e=>e(n))),t)return t(n)},f=setTimeout(u.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=u.bind(null,i.onerror),i.onload=u.bind(null,i.onload),d&&document.head.appendChild(i)}},a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),a.p="/",(()=>{var e={929:0,242:0,170:0,138:0,703:0,994:0};a.f.j=(r,t)=>{var n=a.o(e,r)?e[r]:void 0;if(0!==n)if(n)t.push(n[2]);else if(/^(138|170|242|703|929|994)$/.test(r))e[r]=0;else{var o=new Promise(((t,o)=>n=e[r]=[t,o]));t.push(n[2]=o);var s=a.p+a.u(r),i=new Error;a.l(s,(t=>{if(a.o(e,r)&&(0!==(n=e[r])&&(e[r]=void 0),n)){var o=t&&("load"===t.type?"missing":t.type),s=t&&t.target&&t.target.src;i.message="Loading chunk "+r+" failed.\n("+o+": "+s+")",i.name="ChunkLoadError",i.type=o,i.request=s,n[1](i)}}),"chunk-"+r,r)}},a.O.j=r=>0===e[r];var r=(r,t)=>{var n,o,[s,i,d]=t,l=0;if(s.some((r=>0!==e[r]))){for(n in i)a.o(i,n)&&(a.m[n]=i[n]);if(d)var p=d(a)}for(r&&r(t);l<s.length;l++)o=s[l],a.o(e,o)&&e[o]&&e[o][0](),e[o]=0;return a.O(p)},t=self.webpackChunkpixelfed=self.webpackChunkpixelfed||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})()})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
public/js/spa.js vendored

File diff suppressed because one or more lines are too long

@ -20,19 +20,19 @@
"/js/admin.js": "/js/admin.js?id=fd88b96423314b41cc763a0714554a04",
"/js/rempro.js": "/js/rempro.js?id=f8a8839ec4d1fc5a2fe75a5355fbf39c",
"/js/rempos.js": "/js/rempos.js?id=6adb34adf68f74778365143b28fb5b9b",
"/js/spa.js": "/js/spa.js?id=a83056480ca1135f2f4f547a62ba71e0",
"/js/spa.js": "/js/spa.js?id=931fcbe664a4bad4ca58d888da869b34",
"/js/stories.js": "/js/stories.js?id=814a25875cac8987d85c801dcb453114",
"/js/manifest.js": "/js/manifest.js?id=f73691356be89433fa754ecbe1a56c2c",
"/js/home-0esirpejd.js": "/js/home-0esirpejd.js?id=35becc372b8462690f790baa2be2b41e",
"/js/compose-0esirpejd.js": "/js/compose-0esirpejd.js?id=b499078402ab7a69b78d651fa69ee013",
"/js/post-0esirpejd.js": "/js/post-0esirpejd.js?id=55cbae6dcf96d3e3f0169527d41bf245",
"/js/profile-0esirpejd.js": "/js/profile-0esirpejd.js?id=88a05e19f49e64da20953732e8ffb1fc",
"/js/dmym-0esirpejd.js": "/js/dmym-0esirpejd.js?id=ccecd381f990e7d0675b457d7a4af62a",
"/js/dmyh-0esirpejd.js": "/js/dmyh-0esirpejd.js?id=8c95e04e479de858feb48362c92fa96e",
"/js/daci-0esirpejd.js": "/js/daci-0esirpejd.js?id=744bae95d2ed64035f37c0593e912fe1",
"/js/dffc-0esirpejd.js": "/js/dffc-0esirpejd.js?id=1db9143a4713c2effd4a978421a3b917",
"/js/dsfc-0esirpejd.js": "/js/dsfc-0esirpejd.js?id=28803099b94a995229101b75d9cb9c4f",
"/js/dssc-0esirpejd.js": "/js/dssc-0esirpejd.js?id=fa06d4a8101e0b2f5f7da4b0db831949",
"/js/manifest.js": "/js/manifest.js?id=a298b1dc4eac00125187fb43f0ae8416",
"/js/home-nza92p6rg.js": "/js/home-nza92p6rg.js?id=534f880cc41ea4101f108ba26631ade6",
"/js/compose-nza92p6rg.js": "/js/compose-nza92p6rg.js?id=b9c298d9a8866c4cd621222c92cec661",
"/js/post-nza92p6rg.js": "/js/post-nza92p6rg.js?id=780632681af3f15e920dbcaf7348ae65",
"/js/profile-nza92p6rg.js": "/js/profile-nza92p6rg.js?id=59d7a9f3d48899916e30627373fd0bc2",
"/js/dmym-nza92p6rg.js": "/js/dmym-nza92p6rg.js?id=1b1176d78c05d5300df4199114cd5f10",
"/js/dmyh-nza92p6rg.js": "/js/dmyh-nza92p6rg.js?id=0fe80e2c037c3a1df9b24f9520cbaa4a",
"/js/daci-nza92p6rg.js": "/js/daci-nza92p6rg.js?id=6d9e3404e4e6b40ac19e8c5c70c45fb2",
"/js/dffc-nza92p6rg.js": "/js/dffc-nza92p6rg.js?id=a1871137c3f6d275d3dc34584181402e",
"/js/dsfc-nza92p6rg.js": "/js/dsfc-nza92p6rg.js?id=93ee8e8b8f3a327ea01b2255e08bb2a0",
"/js/dssc-nza92p6rg.js": "/js/dssc-nza92p6rg.js?id=9d7a06ddb6de2fbf1eec7c7589bf1139",
"/css/appdark.css": "/css/appdark.css?id=65bb8633bbd34c87111591cab68cf3dc",
"/css/app.css": "/css/app.css?id=f2e24fbb268e9946443459877f623d98",
"/css/spa.css": "/css/spa.css?id=8f0ae3d3a6614e8a1fe6687d58f6b806",

Loading…
Cancel
Save