Lots of new stuff.

This commit is contained in:
gtoriadotnet 2021-12-15 22:54:04 -05:00
parent 2c25af9efc
commit b50d89d539
21 changed files with 459 additions and 193 deletions

Binary file not shown.

Binary file not shown.

View File

@ -16,8 +16,6 @@ class Kernel extends HttpKernel
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
@ -64,5 +62,6 @@ class Kernel extends HttpKernel
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'cors' => \App\Http\Middleware\Cors::class,
'maintenance' => \App\Http\Middleware\PreventRequestsDuringMaintenance::class,
];
}

View File

@ -2,16 +2,144 @@
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
use Closure;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
use Symfony\Component\HttpKernel\Exception\HttpException;
class PreventRequestsDuringMaintenance extends Middleware
class PreventRequestsDuringMaintenance
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
* The application implementation.
*
* @var \Illuminate\Contracts\Foundation\Application
*/
protected $app;
/**
* The URIs that should be accessible while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
protected $except = [];
/**
* Create a new middleware instance.
*
* @param \Illuminate\Contracts\Foundation\Application $app
* @return void
*/
public function __construct(Application $app)
{
$this->app = $app;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*
* @throws \Symfony\Component\HttpKernel\Exception\HttpException
*/
public function handle($request, Closure $next)
{
if ($this->app->isDownForMaintenance()) {
$data = json_decode(file_get_contents($this->app->storagePath().'/framework/down'), true);
if (isset($data['secret']) && $request->path() === $data['secret']) {
return $this->bypassResponse($data['secret']);
}
if ($this->hasValidBypassCookie($request, $data) ||
$this->inExceptArray($request)) {
return $next($request);
}
return response('{"errors":[{"code":503,"message":"ServiceUnavailable"}]}', 503)
->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8');
}
return $next($request);
}
/**
* Determine if the incoming request has a maintenance mode bypass cookie.
*
* @param \Illuminate\Http\Request $request
* @param array $data
* @return bool
*/
protected function hasValidBypassCookie($request, array $data)
{
return isset($data['secret']) &&
$request->cookie('laravel_maintenance') &&
MaintenanceModeBypassCookie::isValid(
$request->cookie('laravel_maintenance'),
$data['secret']
);
}
/**
* Determine if the request has a URI that should be accessible in maintenance mode.
*
* @param \Illuminate\Http\Request $request
* @return bool
*/
protected function inExceptArray($request)
{
foreach ($this->except as $except) {
if ($except !== '/') {
$except = trim($except, '/');
}
if ($request->fullUrlIs($except) || $request->is($except)) {
return true;
}
}
return false;
}
/**
* Redirect the user back to the root of the application with a maintenance mode bypass cookie.
*
* @param string $secret
* @return \Illuminate\Http\RedirectResponse
*/
protected function bypassResponse(string $secret)
{
return redirect('/')->withCookie(
MaintenanceModeBypassCookie::create($secret)
);
}
/**
* Get the headers that should be sent with the response.
*
* @param array $data
* @return array
*/
protected function getHeaders($data)
{
$headers = isset($data['retry']) ? ['Retry-After' => $data['retry']] : [];
if (isset($data['refresh'])) {
$headers['Refresh'] = $data['refresh'];
}
return $headers;
}
/**
* Get the URIs that should be accessible even when maintenance mode is enabled.
*
* @return array
*/
public function getExcludedPaths()
{
return $this->except;
}
}

11
web/app/Models/FFlag.php Normal file
View File

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class FFlag extends Model
{
use HasFactory;
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class FastGroup extends Model
{
use HasFactory;
}

View File

@ -11,7 +11,6 @@
"guzzlehttp/guzzle": "^7.0.1",
"laravel/framework": "^8.54",
"laravel/sail": "^1.12",
"laravel/sanctum": "^2.11",
"laravel/tinker": "^2.5",
"laravel/ui": "^3.3",
"predis/predis": "^1.1"

66
web/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "eae1aa1a609fc45f372619bc8e23cafc",
"content-hash": "c6a0e979567b55245388bdaffddfe2e4",
"packages": [
{
"name": "asm89/stack-cors",
@ -1165,70 +1165,6 @@
},
"time": "2021-10-26T21:37:54+00:00"
},
{
"name": "laravel/sanctum",
"version": "v2.11.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/sanctum.git",
"reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/sanctum/zipball/b21e65cbe13896946986cb0868180cd69e1bd5d3",
"reference": "b21e65cbe13896946986cb0868180cd69e1bd5d3",
"shasum": ""
},
"require": {
"ext-json": "*",
"illuminate/contracts": "^6.9|^7.0|^8.0",
"illuminate/database": "^6.9|^7.0|^8.0",
"illuminate/support": "^6.9|^7.0|^8.0",
"php": "^7.2|^8.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^4.0|^5.0|^6.0",
"phpunit/phpunit": "^8.0|^9.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
},
"laravel": {
"providers": [
"Laravel\\Sanctum\\SanctumServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Sanctum\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
"keywords": [
"auth",
"laravel",
"sanctum"
],
"support": {
"issues": "https://github.com/laravel/sanctum/issues",
"source": "https://github.com/laravel/sanctum"
},
"time": "2021-06-15T15:56:21+00:00"
},
{
"name": "laravel/tinker",
"version": "v2.6.1",

View File

@ -1,51 +0,0 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Stateful Domains
|--------------------------------------------------------------------------
|
| Requests from the following domains / hosts will receive stateful API
| authentication cookies. Typically, these should include your local
| and production domains which access your API via a frontend SPA.
|
*/
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),
/*
|--------------------------------------------------------------------------
| Expiration Minutes
|--------------------------------------------------------------------------
|
| This value controls the number of minutes until an issued token will be
| considered expired. If this value is null, personal access tokens do
| not expire. This won't tweak the lifetime of first-party sessions.
|
*/
'expiration' => null,
/*
|--------------------------------------------------------------------------
| Sanctum Middleware
|--------------------------------------------------------------------------
|
| When authenticating your first-party SPA with Sanctum you may need to
| customize some of the middleware Sanctum uses while processing the
| request. You may change the middleware listed below as required.
|
*/
'middleware' => [
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
],
];

View File

@ -1,36 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreatePersonalAccessTokensTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->bigIncrements('id');
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('personal_access_tokens');
}
}

View File

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFflagsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('fflags', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('value');
$table->enum('dataType', ['Log', 'Int', 'String']);
$table->enum('type', ['Raw', 'Fast', 'Dynamic', 'Shared']);
$table->bigInteger('groupId');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('fflags');
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFastgroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('fastgroups', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('protected')->default(false);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('fastgroups');
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\FFlag;
use App\Models\FastGroup;
class FFlagSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$clientAppSettings = FastGroup::create([
'name' => 'ClientAppSettings'
]);
$cloudAppSettings = FastGroup::create([
'name' => 'CloudCompute'
]);
$clientSharedSettings = FastGroup::create([
'name' => 'ClientSharedSettings'
]);
$arbiterAppSettings = FastGroup::create([
'name' => 'Arbiter'
]);
$windowsBootstrapperSettings = FastGroup::create([
'name' => 'WindowsBootstrapperSettings'
]);
$windowsStudioBootstrapperSettings = FastGroup::create([
'name' => 'WindowsStudioBootstrapperSettings'
]);
}
}

79
web/package-lock.json generated
View File

@ -1242,6 +1242,23 @@
"@babel/runtime": "^7.6.2"
}
},
"@react-three/fiber": {
"version": "7.0.24",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-7.0.24.tgz",
"integrity": "sha512-CJi1Mex7jqByTEVZoUzg0xZEw63CUjm4bUDx0XIhuAmNUsmFmht7cRt87zUQSSDQvmaDqvoDWW7dD+uFJW/kUQ==",
"requires": {
"@babel/runtime": "^7.13.10",
"react-merge-refs": "^1.1.0",
"react-reconciler": "^0.26.2",
"react-three-fiber": "0.0.0-deprecated",
"react-use-measure": "^2.1.1",
"resize-observer-polyfill": "^1.5.1",
"scheduler": "^0.20.2",
"use-asset": "^1.0.4",
"utility-types": "^3.10.0",
"zustand": "^3.5.1"
}
},
"@restart/context": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@restart/context/-/context-2.1.4.tgz",
@ -3146,6 +3163,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz",
"integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw=="
},
"debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
"integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
},
"debug": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
@ -6548,6 +6570,21 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-merge-refs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz",
"integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ=="
},
"react-reconciler": {
"version": "0.26.2",
"resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.26.2.tgz",
"integrity": "sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q==",
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"scheduler": "^0.20.2"
}
},
"react-router": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.1.tgz",
@ -6598,6 +6635,11 @@
"tiny-warning": "^1.0.0"
}
},
"react-three-fiber": {
"version": "0.0.0-deprecated",
"resolved": "https://registry.npmjs.org/react-three-fiber/-/react-three-fiber-0.0.0-deprecated.tgz",
"integrity": "sha512-EblIqTAsIpkYeM8bZtC4lcpTE0A2zCEGipFB52RgcQq/q+0oryrk7Sxt+sqhIjUu6xMNEVywV8dr74lz5yWO6A=="
},
"react-transition-group": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz",
@ -6609,6 +6651,14 @@
"prop-types": "^15.6.2"
}
},
"react-use-measure": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz",
"integrity": "sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==",
"requires": {
"debounce": "^1.2.1"
}
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
@ -6759,6 +6809,11 @@
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"resolve": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
@ -6939,7 +6994,6 @@
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz",
"integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
@ -7513,6 +7567,11 @@
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"three": {
"version": "0.135.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.135.0.tgz",
"integrity": "sha512-kuEpuuxRzLv0MDsXai9huCxOSQPZ4vje6y0gn80SRmQvgz6/+rI0NAvCRAw56zYaWKMGMfqKWsxF9Qa2Z9xymQ=="
},
"thunky": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
@ -7694,6 +7753,14 @@
}
}
},
"use-asset": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/use-asset/-/use-asset-1.0.4.tgz",
"integrity": "sha512-7/hqDrWa0iMnCoET9W1T07EmD4Eg/Wmoj/X8TGBc++ECRK4m5yTsjP4O6s0yagbxfqIOuUkIxe2/sA+VR2GxZA==",
"requires": {
"fast-deep-equal": "^3.1.3"
}
},
"util": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
@ -7717,6 +7784,11 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
"utility-types": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
"integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg=="
},
"utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@ -8150,6 +8222,11 @@
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true
},
"zustand": {
"version": "3.6.7",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.6.7.tgz",
"integrity": "sha512-bYWKXMfoJwZyliFgidcQ3tJC/F2f2hHq1+lhTk8dVPX2k28i4VnpnKjBGNxAd2QNliV0m455Vm+gDL8LShrV3g=="
}
}
}

View File

@ -29,11 +29,13 @@
"webpack-subresource-integrity": "^5.0.0"
},
"dependencies": {
"@react-three/fiber": "^7.0.24",
"@steveeeie/react-page-transition": "^1.2.1",
"laravel-mix-react-css-modules": "^2.0.0",
"mini-css-extract-plugin": "^2.4.3",
"react-bootstrap": "^2.0.2",
"react-google-recaptcha": "^2.1.0",
"styled-components": "^5.3.1"
"styled-components": "^5.3.1",
"three": "^0.135.0"
}
}

View File

@ -9,6 +9,8 @@ import Navbar from '../components/Navbar.js';
import Banner from '../components/Banner.js';
import Footer from '../components/Footer.js';
import Loader from '../Components/Loader.js';
import { Home } from '../Pages/Home.js';
import { Auth } from '../Pages/Auth.js';
@ -29,7 +31,7 @@ var protocol = Config.Protocol;
class App extends React.Component {
constructor(props) {
super(props);
this.state = {maintenance: false, theme: 0, banners: []};
this.state = {maintenance: false, theme: 0, banners: [], offlineFetched: false};
}
componentDidMount() {
@ -37,22 +39,38 @@ class App extends React.Component {
function updateBanners()
{
axios.get(protocol + 'apis.' + url + '/banners/data').then((response) => {
var result = [];
response.data.map(function(banner){
result.push(<Banner type={banner.type} description={banner.text} dismissible={banner.dismissable} />);
axios.get(protocol + 'apis.' + url + '/banners/data')
.then((response) => {
var result = [];
response.data.map(function(banner){
result.push(<Banner type={banner.type} description={banner.text} dismissible={banner.dismissable} />);
});
app.setState({banners: result});
});
app.setState({banners: result});
});
}
if(this.state.maintenance === true)
function updateOfflineStatus()
{
this.setState({theme: 1});
axios.get(protocol + 'apis.' + url + '/')
.then((response) => {
app.setState({maintenance: false});
})
.catch((error) => {
if (error.response)
{
if(error.response.status == 503)
app.setState({maintenance: true, theme: 1});
}
})
.finally(() => {
app.setState({offlineFetched: true});
});
}
updateBanners();
updateOfflineStatus();
setInterval(updateBanners, 2*60*1000 /* 2 mins */);
setInterval(updateOfflineStatus, 10*60*1000 /* 10 mins */);
}
render() {
@ -60,8 +78,9 @@ class App extends React.Component {
document.documentElement.classList.remove(!(this.state.theme === 0) ? 'gtoria-light' : 'gtoria-dark');
return (
this.state.offlineFetched == true ?
<Router>
<Navbar maintenanceEnabled={false} />
<Navbar maintenanceEnabled={this.state.maintenance} />
{
this.state.banners.length !== 0 ?
@ -134,6 +153,10 @@ class App extends React.Component {
);
}}/>
</Router>
:
<div className="gtoria-loader-center">
<Loader />
</div>
);
}
}

View File

@ -23,7 +23,7 @@ const LoginForm = (props) => {
</div>
<div className="col">
<h5>New to Graphictoria?</h5>
<p>Creating an account takes less than a minute, and you can join a community of 6k+ users for <b>completely free</b>.<br/><Link to="/register" className="text-decoration-none fw-normal">Sign Up</Link></p>
<p>Creating an account takes less than a minute, and you can join a community of 7k+ users for <b>completely free</b>.<br/><Link to="/register" className="text-decoration-none fw-normal">Sign Up</Link></p>
</div>
</>
);

View File

@ -22,7 +22,7 @@ class Home extends React.Component {
<div className="container graphictoria-center-vh my-auto text-center text-white">
<div className="mb-4 graphictoria-home-shadow">
<h1 className="graphictoria-homepage-header">Graphictoria</h1>
<h5 className="mb-0">Graphictoria aims to revive the classic Roblox experience. Join <b>6k+</b> other users and relive your childhood!</h5>
<h5 className="mb-0">Graphictoria aims to revive the classic Roblox experience. Join <b>7k+</b> other users and relive your childhood!</h5>
<p className="graphictoria-homepage-fine-print fst-italic">* Graphictoria is not affiliated with, endorsed by, or sponsored by Roblox Corporation.</p>
</div>
<Link to="/register" className="btn btn-success">Create your account<i className="ps-2 graphictoria-small-aligned-text fas fa-chevron-right"></i></Link>

View File

@ -1,13 +1,47 @@
// © XlXi 2021
// Graphictoria 5
import React from "react";
import React, { useRef } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import SetTitle from "../Helpers/Title.js";
let Buttons = [];
let ButtonsAlreadyTemplated = false;
function Box(props) {
const ref = useRef();
const distanceFromCamera = Math.random() * 30
const rotX = (Math.random() * 200 - 100)/300
const rotZ = (Math.random() * 200 - 100)/300
useFrame((state, delta) => {
ref.current.position.y -= 0.6 * delta
ref.current.rotation.x += rotX * delta
ref.current.rotation.z += rotZ * delta
if(ref.current.position.y < -30)
{
ref.current.position.y = 30;
}
});
return (
<mesh
{...props}
ref={ref}
scale={1}
position={[(Math.random() * 120) - 60, (Math.random() * 60) - 30, -distanceFromCamera]}
rotation={[Math.random() * 360, Math.random() * 360, Math.random() * 360]}>
<boxGeometry args={[1, 0.3, 0.5]} />
<meshStandardMaterial color={'grey'} />
</mesh>
)
}
function MakeButtons()
{
if(!ButtonsAlreadyTemplated)
@ -37,20 +71,31 @@ class Maintenance extends React.Component {
{
MakeButtons();
return (
<div className="text-center mt-auto container">
<h1>Graphictoria is currently under maintenance.</h1>
<h4>Our advanced team of cyber monkes are working to make Graphictoria better. We'll be back soon!</h4>
<div className="input-group mt-5">
<input type="password" className="form-control" placeholder="Password" autoComplete="off"/>
{
Buttons.map(character => (
<React.Fragment key={character.id}>
<button className="btn btn-secondary" type="button" onClick={ () => DoButton(character.id) }>{character.value}</button>
</React.Fragment>
))
}
<>
<div className="gtoria-maintenance-background">
<Canvas>
<ambientLight />
<pointLight position={[10, 10, 10]} />
{
[...Array(100)].map((e, i) => (<Box key={i}/>))
}
</Canvas>
</div>
</div>
<div className="text-center mt-auto container">
<h1>Graphictoria is currently under maintenance.</h1>
<h4>Our advanced team of cyber monkes are working to make Graphictoria better. We'll be back soon!</h4>
<div className="input-group mt-5">
<input type="password" className="form-control" placeholder="Password" autoComplete="off"/>
{
Buttons.map(character => (
<React.Fragment key={character.id}>
<button className="btn btn-secondary" type="button" onClick={ () => DoButton(character.id) }>{character.value}</button>
</React.Fragment>
))
}
</div>
</div>
</>
);
}
}

View File

@ -21,8 +21,20 @@ $web-font-path: "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,w
border-width: 0 1px $width 1px;
}
// Maintenance
.gtoria-maintenance-background {
position: absolute;
width: 100%;
height: 100%;
z-index: -9999;
}
// Loader
.gtoria-loader-center {
margin: auto;
}
.gtoria-loader {
display: inline-block;
position: relative;

View File

@ -16,12 +16,11 @@ use App\Http\Controllers\GamesController;
|
*/
Route::middleware(['cors'])->group(function() {
Route::middleware(['cors', 'maintenance'])->group(function() {
Route::get('/', function () {
return 'API OK';
});
Route::get('/banners/data', [BannerController::class, 'getBanners']);
Route::get('/games/metadata', [GamesController::class, 'isAvailable']);
@ -31,5 +30,4 @@ Route::middleware(['cors'])->group(function() {
->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8');
});
});