mirror of
https://github.com/linuxserver/Heimdall.git
synced 2026-03-02 08:23:35 +09:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2184eef0a | ||
|
|
fbd050d4e4 | ||
|
|
5d67f570a9 | ||
|
|
7d016cdaa6 | ||
|
|
6e954a355d | ||
|
|
60faccad27 | ||
|
|
1f5493ac98 | ||
|
|
9c117b7946 | ||
|
|
c72fee9644 | ||
|
|
0999bebcb4 | ||
|
|
1c41e3d1ef | ||
|
|
ed3cd79c92 |
16
.github/workflows/call_issue_pr_tracker.yml
vendored
Normal file
16
.github/workflows/call_issue_pr_tracker.yml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
name: Issue & PR Tracker
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened,reopened,labeled,unlabeled,closed]
|
||||
pull_request_target:
|
||||
types: [opened,reopened,review_requested,review_request_removed,labeled,unlabeled,closed]
|
||||
pull_request_review:
|
||||
types: [submitted,edited,dismissed]
|
||||
|
||||
jobs:
|
||||
manage-project:
|
||||
permissions:
|
||||
issues: write
|
||||
uses: linuxserver/github-workflows/.github/workflows/issue-pr-tracker.yml@v1
|
||||
secrets: inherit
|
||||
13
.github/workflows/call_issues_cron.yml
vendored
Normal file
13
.github/workflows/call_issues_cron.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: Mark stale issues and pull requests
|
||||
on:
|
||||
schedule:
|
||||
- cron: '35 15 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
uses: linuxserver/github-workflows/.github/workflows/issues-cron.yml@v1
|
||||
secrets: inherit
|
||||
@@ -14,15 +14,15 @@ function format_bytes($bytes, bool $is_drive_size = true, string $beforeunit = '
|
||||
$btype = ($is_drive_size === true) ? 1000 : 1024;
|
||||
$labels = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||||
// use 1000 rather than 1024 to simulate HD size not real size
|
||||
for ($x = 0; $bytes >= $btype && $x < (count($labels) - 1); $bytes /= $btype, $x++);
|
||||
for ($x = 0; $bytes >= $btype && $x < (count($labels) - 1); $bytes /= $btype, $x++) ;
|
||||
if ($labels[$x] == 'TB') {
|
||||
return round($bytes, 3).$beforeunit.$labels[$x].$afterunit;
|
||||
return round($bytes, 3) . $beforeunit . $labels[$x] . $afterunit;
|
||||
} elseif ($labels[$x] == 'GB') {
|
||||
return round($bytes, 2).$beforeunit.$labels[$x].$afterunit;
|
||||
return round($bytes, 2) . $beforeunit . $labels[$x] . $afterunit;
|
||||
} elseif ($labels[$x] == 'MB') {
|
||||
return round($bytes, 2).$beforeunit.$labels[$x].$afterunit;
|
||||
return round($bytes, 2) . $beforeunit . $labels[$x] . $afterunit;
|
||||
} else {
|
||||
return round($bytes, 0).$beforeunit.$labels[$x].$afterunit;
|
||||
return round($bytes, 0) . $beforeunit . $labels[$x] . $afterunit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ function str_slug($title, string $separator = '-', string $language = 'en'): str
|
||||
return Str::slug($title, $separator, $language);
|
||||
}
|
||||
|
||||
if (! function_exists('str_is')) {
|
||||
if (!function_exists('str_is')) {
|
||||
/**
|
||||
* Determine if a given string matches a given pattern.
|
||||
*
|
||||
* @param string|array $pattern
|
||||
* @param string|array $pattern
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*
|
||||
@@ -64,7 +64,7 @@ function get_brightness($hex)
|
||||
// $hex = str_replace('#', '', $hex);
|
||||
$hex = preg_replace("/[^0-9A-Fa-f]/", '', $hex);
|
||||
if (strlen($hex) == 3) {
|
||||
$hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
|
||||
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
|
||||
}
|
||||
|
||||
$c_r = hexdec(substr($hex, 0, 2));
|
||||
@@ -97,7 +97,7 @@ function getLinkTargetAttribute(): string
|
||||
if ($target === 'current') {
|
||||
return '';
|
||||
} else {
|
||||
return ' target="'.$target.'"';
|
||||
return ' target="' . $target . '"';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,3 +109,28 @@ function className($name)
|
||||
{
|
||||
return preg_replace('/[^\p{L}\p{N}]/u', '', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
* @param string $extension
|
||||
* @return bool
|
||||
*/
|
||||
function isImage(string $file, string $extension): bool
|
||||
{
|
||||
$allowedExtensions = ['jpg', 'jpeg', 'png', 'bmp', 'gif', 'svg', 'webp'];
|
||||
|
||||
if (!in_array($extension, $allowedExtensions)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tempFileName = tempnam("/tmp", "image-check-");
|
||||
$handle = fopen($tempFileName, "w");
|
||||
|
||||
fwrite($handle, $file);
|
||||
|
||||
$size = @getimagesize($tempFileName);
|
||||
|
||||
fclose($handle);
|
||||
|
||||
return is_array($size) && str_starts_with($size['mime'], 'image');
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ use Illuminate\Routing\Redirector;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
@@ -140,7 +141,7 @@ class ItemController extends Controller
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$trash = (bool) $request->input('trash');
|
||||
$trash = (bool)$request->input('trash');
|
||||
|
||||
$data['apps'] = Item::ofType('item')->orderBy('title', 'asc')->get();
|
||||
$data['trash'] = Item::ofType('item')->onlyTrashed()->get();
|
||||
@@ -196,6 +197,7 @@ class ItemController extends Controller
|
||||
* @param Request $request
|
||||
* @param null $id
|
||||
* @return Item
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public static function storelogic(Request $request, $id = null): Item
|
||||
{
|
||||
@@ -203,6 +205,7 @@ class ItemController extends Controller
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'url' => 'required',
|
||||
'file' => 'image'
|
||||
]);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
@@ -217,17 +220,18 @@ class ItemController extends Controller
|
||||
"verify_peer_name" => false,
|
||||
),
|
||||
);
|
||||
|
||||
$file = $request->input('icon');
|
||||
$path_parts = pathinfo($file);
|
||||
$extension = $path_parts['extension'];
|
||||
|
||||
$contents = file_get_contents($request->input('icon'), false, stream_context_create($options));
|
||||
|
||||
if ($application) {
|
||||
$icon = $application->icon;
|
||||
} else {
|
||||
$file = $request->input('icon');
|
||||
$path_parts = pathinfo($file);
|
||||
$icon = md5($contents);
|
||||
$icon .= '.' . $path_parts['extension'];
|
||||
if (!isImage($contents, $extension)) {
|
||||
throw ValidationException::withMessages(['file' => 'Icon must be an image.']);
|
||||
}
|
||||
$path = 'icons/' . $icon;
|
||||
|
||||
$path = 'icons/' . ($application ? $application->icon : md5($contents) . '.' . $extension);
|
||||
|
||||
// Private apps could have here duplicated icons folder
|
||||
if (strpos($path, 'icons/icons/') !== false) {
|
||||
@@ -334,7 +338,7 @@ class ItemController extends Controller
|
||||
public function destroy(Request $request, int $id): RedirectResponse
|
||||
{
|
||||
//
|
||||
$force = (bool) $request->input('force');
|
||||
$force = (bool)$request->input('force');
|
||||
if ($force) {
|
||||
Item::withTrashed()
|
||||
->where('id', $id)
|
||||
@@ -388,11 +392,11 @@ class ItemController extends Controller
|
||||
$output['custom'] = null;
|
||||
|
||||
$app = Application::single($appid);
|
||||
$output = (array) $app;
|
||||
$output = (array)$app;
|
||||
|
||||
$appdetails = Application::getApp($appid);
|
||||
|
||||
if ((bool) $app->enhanced === true) {
|
||||
if ((bool)$app->enhanced === true) {
|
||||
// if(!isset($app->config)) { // class based config
|
||||
$output['custom'] = className($appdetails->name) . '.config';
|
||||
// }
|
||||
@@ -438,7 +442,7 @@ class ItemController extends Controller
|
||||
}
|
||||
|
||||
$app_details = new $app();
|
||||
$app_details->config = (object) $data;
|
||||
$app_details->config = (object)$data;
|
||||
$app_details->test();
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,10 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
if ($setting->type === 'image') {
|
||||
$validatedData = $request->validate([
|
||||
'value' => 'image'
|
||||
]);
|
||||
|
||||
if (!$request->hasFile('value')) {
|
||||
throw new \Exception(
|
||||
'file_too_big'
|
||||
|
||||
@@ -57,6 +57,7 @@ class TagController extends Controller
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'file' => 'image'
|
||||
]);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
@@ -129,6 +130,7 @@ class TagController extends Controller
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'title' => 'required|max:255',
|
||||
'file' => 'image'
|
||||
]);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
|
||||
@@ -62,7 +62,7 @@ class UserController extends Controller
|
||||
'email' => 'required|email',
|
||||
'password' => 'nullable|confirmed',
|
||||
'password_confirmation' => 'nullable',
|
||||
|
||||
'file' => 'image'
|
||||
]);
|
||||
$user = new User;
|
||||
$user->username = $request->input('username');
|
||||
@@ -129,6 +129,7 @@ class UserController extends Controller
|
||||
'email' => 'required|email',
|
||||
'password' => 'nullable|confirmed',
|
||||
'password_confirmation' => 'nullable',
|
||||
'file' => 'image'
|
||||
]);
|
||||
//die(print_r($request->all()));
|
||||
|
||||
|
||||
@@ -73,7 +73,12 @@ class AppServiceProvider extends ServiceProvider
|
||||
}
|
||||
|
||||
$alt_bg = '';
|
||||
if ($bg_image = Setting::fetch('background_image')) {
|
||||
$trianglify = 'false';
|
||||
$trianglify_seed = null;
|
||||
if (Setting::fetch('trianglify')) {
|
||||
$trianglify = 'true';
|
||||
$trianglify_seed = Setting::fetch('trianglify_seed');
|
||||
} elseif ($bg_image = Setting::fetch('background_image')) {
|
||||
$alt_bg = ' style="background-image: url(storage/'.$bg_image.')"';
|
||||
}
|
||||
|
||||
@@ -81,6 +86,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
$current_user = User::currentUser();
|
||||
|
||||
$view->with('alt_bg', $alt_bg);
|
||||
$view->with('trianglify', $trianglify);
|
||||
$view->with('trianglify_seed', $trianglify_seed);
|
||||
$view->with('allusers', $allusers);
|
||||
$view->with('current_user', $current_user);
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ return [
|
||||
*/
|
||||
|
||||
'name' => env('APP_NAME', 'Heimdall'),
|
||||
'version' => '2.5.6',
|
||||
'version' => '2.5.7',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -180,6 +180,33 @@ class SettingsSeeder extends Seeder
|
||||
$setting->value = 'en';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if (! $setting = Setting::find(12)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 12;
|
||||
$setting->group_id = 2;
|
||||
$setting->key = 'trianglify';
|
||||
$setting->type = 'boolean';
|
||||
$setting->label = 'app.settings.trianglify';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->label = 'app.settings.trianglify';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
if (! $setting = Setting::find(13)) {
|
||||
$setting = new Setting;
|
||||
$setting->id = 13;
|
||||
$setting->group_id = 2;
|
||||
$setting->key = 'trianglify_seed';
|
||||
$setting->type = 'text';
|
||||
$setting->value = 'heimdall';
|
||||
$setting->label = 'app.settings.trianglify_seed';
|
||||
$setting->save();
|
||||
} else {
|
||||
$setting->label = 'app.settings.trianglify_seed';
|
||||
$setting->save();
|
||||
}
|
||||
|
||||
$window_target_options = json_encode([
|
||||
'current' => 'app.settings.window_target.current',
|
||||
|
||||
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
1
public/js/trianglify.js
vendored
Normal file
1
public/js/trianglify.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/mix-manifest.json
generated
2
public/mix-manifest.json
generated
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"/css/app.css": "/css/app.css?id=55e02812d34a73b4386802d27fbcd6e8",
|
||||
"/js/app.js": "/js/app.js?id=14f3726628b93f64bd3d12e46e815521"
|
||||
"/js/app.js": "/js/app.js?id=3377b9b80073713e4dc54937c94aa6ad"
|
||||
}
|
||||
|
||||
27
readme.md
27
readme.md
@@ -22,10 +22,10 @@ Why not use it as your browser start page? It even has the ability to include a
|
||||

|
||||
|
||||
## Video
|
||||
If you want to see a quick video of it in use, go to https://youtu.be/GXnnMAxPzMc
|
||||
If you want to see a quick video of Heimdall in use, go to https://youtu.be/GXnnMAxPzMc
|
||||
|
||||
## Supported applications
|
||||
You can use the app to link to any site or application, but Foundation apps will auto fill in the icon for the app and supply a default color for the tile. In addition Enhanced apps allow you provide details to an apps API, allowing you to view live stats directly on the dashboad. For example, the NZBGet and Sabnzbd Enhanced apps will display the queue size and download speed while something is downloading.
|
||||
You can use the app to link to any site or application, but Foundation apps will auto fill in the icon for the app and supply a default color for the tile. In addition, Enhanced apps allow you provide details to an apps API, allowing you to view live stats directly on the dashboad. For example, the NZBGet and Sabnzbd Enhanced apps will display the queue size, and download speed while something is downloading.
|
||||
|
||||
Supported applications are recognized by the title of the application as entered in the title field when adding an application. For example, to add a link to pfSense, begin by typing "p" in the title field and then select "pfSense" from the list of supported applications.
|
||||
|
||||
@@ -36,7 +36,7 @@ Supported applications are recognized by the title of the application as entered
|
||||
## Installing
|
||||
Apart from the Laravel 8 dependencies, namely PHP >= 7.4.32, BCMath PHP Extension, INTL PHP Extension, Ctype PHP Extension, Fileinfo PHP extension, JSON PHP Extension, Mbstring PHP Extension, OpenSSL PHP Extension, PDO PHP Extension, Tokenizer PHP Extension, XML PHP Extension, the only other thing Heimdall needs is sqlite support and zip support (php-zip).
|
||||
|
||||
If you find you can't change the background make sure `php_fileinfo` is enabled in your php.ini. I believe it should be by default, but one user came across the issue on a windows system.
|
||||
If you find you can't change the background make sure `php_fileinfo` is enabled in your php.ini. I believe `php_fileinfo` should be enabled by default, but one user came across the issue on a windows system.
|
||||
|
||||
Installation is as simple as cloning the repository somewhere, or downloading and extracting the zip/tar and pointing your httpd document root to the `/public` folder then creating the .env file and generating an encryption key (this is all taken care of for you with the docker).
|
||||
|
||||
@@ -62,10 +62,10 @@ Options are stored in `/storage/app/searchproviders.yaml` (`/config/www/searchpr
|
||||
|
||||
Consider contributing to https://github.com/linuxserver/Heimdall/discussions/categories/search-providers to help others add new ones.
|
||||
|
||||
The item at the top of the list `Tiles` allows you to search for apps on your dashboard by name, helpful when you have lots of icons.
|
||||
The item at the top of the list `Tiles` allows you to search for apps on your dashboard by name, this can be helpful when you have lots of icons.
|
||||
|
||||
## New background image not being set
|
||||
If you are using the docker image or a default php install you may find images over 2MB wont get set as the background image, you just need to change the `upload_max_filesize` in the php.ini.
|
||||
If you are using the docker image or a default php install you may find images over 2MB won't get set as the background image, you just need to change the `upload_max_filesize` in the php.ini.
|
||||
|
||||
If you are using the linuxserver.io docker image simply edit `/path/to/config/php/php-local.ini` and add `upload_max_filesize = 30M` to the end.
|
||||
|
||||
@@ -75,7 +75,7 @@ If you are running the docker and the EnhancedApps you are using are also in doc
|
||||
You can do this by using `http(s)://docker_name:port` in the config section. Instead of the name you can use the internal docker ip, this usually starts with `172.`
|
||||
|
||||
## Languages
|
||||
The app has been translated into several languages; however, the quality of the translations could do with work. If you would like to improve them, or help with other translations, they are stored in `/resources/lang/`.
|
||||
The app has been translated into several languages; however, the quality of the translations could benefit from some work. If you would like to improve them, or help with other translations, they are stored in `/resources/lang/`.
|
||||
|
||||
To create a new language translation, make a new folder with the ISO 3166-1 alpha-2 code as the name, copy `app.php` from `/resources/lang/en/app.php` into your new folder and replace the English strings.
|
||||
|
||||
@@ -145,15 +145,15 @@ location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
```
|
||||
Someone was using the same nginx setup to both run this and reverse proxy Plex, Plex is served from `/web` so their location was interfering with the `/webfonts`.
|
||||
Someone was using the same Nginx setup to both run this and reverse proxy Plex. Plex is served from `/web` so their location was interfering with the `/webfonts`.
|
||||
|
||||
Therefore, if your fonts aren't showing because you have a location for `/web`, add the following
|
||||
Therefore, if your fonts aren't showing because you have a location for `/web`, add the following:
|
||||
```
|
||||
location /webfonts {
|
||||
try_files $uri $uri/;
|
||||
}
|
||||
```
|
||||
If there are any other locations which might interfere with any of the folders in the `/public` folder, you might have to do the same for those as well, but it's a super fringe case.
|
||||
If there are any other locations that might interfere with any of the folders in the `/public` folder, you might have to do the same for those as well, however it's a super fringe case.
|
||||
|
||||
### Reverse proxy
|
||||
If you'd like to reverse proxy this app, we recommend using our letsencrypt/nginx docker image: [SWAG - Secure Web Application Gateway](https://hub.docker.com/r/linuxserver/swag)
|
||||
@@ -181,12 +181,12 @@ Per default Heimdall uses the standard certificate bundle file (`ca-certificates
|
||||
openssl.cafile = /config/heimdall.pem
|
||||
```
|
||||
|
||||
Restart the container and the enhanced apps should now be able to access your local HTTP websites. This configuration will survive updating or recreating the Heimdall container.
|
||||
Restart the container and the Enhanced apps should now be able to access your local HTTP websites. This configuration will survive updating or recreating the Heimdall container.
|
||||
|
||||
## Running offline
|
||||
The apps list is hosted on github, you have a couple of options if you want to run without a connection to the outside world:
|
||||
1) Clone the repository and host it yourself, look at the .github actions file to see how to generate the apps list.
|
||||
2) Download the apps list and store it as a json accessible to heimdall named `list.json`
|
||||
2) Download the apps list and store it as a JSON accessible to Heimdall named `list.json`
|
||||
|
||||
With both options all you need to do is add the following to your `.env`
|
||||
`APP_SOURCE=http://localhost/` Where `http://localhost/` is the path to the apps list without the name of the file, so if your file is stored at `https://heimdall.local/list.json` you would put `APP_SOURCE=https://heimdall.local/`
|
||||
@@ -205,12 +205,13 @@ If you would like to show your appreciation, feel free to use the link below.
|
||||
- JavaScript - [jQuery](https://jquery.com/)
|
||||
- Colour picker - [Huebee](http://huebee.buzz/)
|
||||
- Background image - [pexels](https://www.pexels.com)
|
||||
- Trianglify library - [Trianglify](https://github.com/qrohlf/trianglify)
|
||||
- Everyone at Linuxserver.io that has helped with the app and let's not forget IronicBadger for the following question that started it all:
|
||||
```
|
||||
you know, i would love something like this landing page for all my servers apps
|
||||
You know, I would love something like this landing page for all my servers' apps
|
||||
that gives me the ability to pin favourites
|
||||
and / or search
|
||||
@Stark @Kode do either of you think you'd be able to rustle something like this up ?
|
||||
@Stark @Kode do either of you think you'd be able to rustle something like this up?
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
@@ -86,7 +86,7 @@ $.when($.ready).then(() => {
|
||||
}
|
||||
|
||||
$("#main")
|
||||
.on("mouseenter", "#sortable.ui-sortable-disabled .item", function () {
|
||||
.on("mouseenter", "#sortable .item", function () {
|
||||
$(this).siblings(".tooltip").addClass("active");
|
||||
$(".refresh", this).addClass("active");
|
||||
})
|
||||
|
||||
@@ -17,6 +17,8 @@ return [
|
||||
|
||||
'settings.version' => 'Versão',
|
||||
'settings.background_image' => 'Imagem de fundo',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link é aberto em',
|
||||
'settings.window_target.current' => 'Abra nesta aba',
|
||||
'settings.window_target.one' => 'Abra na mesma aba',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Podpořte nás',
|
||||
'settings.version' => 'Verze',
|
||||
'settings.background_image' => 'Obrázek pozadí',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Odkazy otevírat v',
|
||||
'settings.window_target.current' => 'Otevřít v této záložce',
|
||||
'settings.window_target.one' => 'Otevřít ve stejné záložce',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Doner',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Baggrundsbillede',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link opens in',
|
||||
'settings.window_target.current' => 'Åbn i denne fane',
|
||||
'settings.window_target.one' => 'Åbn i den samme fane',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Spende',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Hintergrundbild',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link öffnen in',
|
||||
'settings.window_target.current' => 'In diesem Tab öffnen',
|
||||
'settings.window_target.one' => 'Im selben Tab öffnen',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Δωρεά',
|
||||
'settings.version' => 'Έκδοση',
|
||||
'settings.background_image' => 'Εικόνα Παρασκηνίου',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Ο Σύνδεσμος ανοίγει σε',
|
||||
'settings.window_target.current' => 'Άνοιγμα σε αυτή την καρτέλα',
|
||||
'settings.window_target.one' => 'Άνοιγμα στην ίδια καρτέλα',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Donate',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Background Image',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link opens in',
|
||||
'settings.window_target.current' => 'Open in this tab',
|
||||
'settings.window_target.one' => 'Open in the same tab',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Donar',
|
||||
'settings.version' => 'Versión',
|
||||
'settings.background_image' => 'Imagen de Fondo',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Vínculo abre en',
|
||||
'settings.window_target.current' => 'Abrir en ésta pestaña',
|
||||
'settings.window_target.one' => 'Abrir en la misma pestaña',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Lahjoita',
|
||||
'settings.version' => 'Versio',
|
||||
'settings.background_image' => 'Taustakuva',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Linkit aukeaa',
|
||||
'settings.window_target.current' => 'Avaa tässä välilehdessä',
|
||||
'settings.window_target.one' => 'Avaa samassa välilehdessä',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Contribuer',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Image d\'arrière-plan',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Ouverture des liens',
|
||||
'settings.window_target.current' => 'Dans l\'onglet courant',
|
||||
'settings.window_target.one' => 'Dans le même nouvel onglet',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Adomány',
|
||||
'settings.version' => 'Verzió',
|
||||
'settings.background_image' => 'Háttérkép',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link megnyitása',
|
||||
'settings.window_target.current' => 'Ezen a lapon',
|
||||
'settings.window_target.one' => 'Azonos lapon',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Dona',
|
||||
'settings.version' => 'Versione',
|
||||
'settings.background_image' => 'Immagine di sfondo',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Apri link in',
|
||||
'settings.window_target.current' => 'Apri in questa scheda',
|
||||
'settings.window_target.one' => 'Apri nella stessa scheda',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => '寄付',
|
||||
'settings.version' => 'バージョン',
|
||||
'settings.background_image' => '背景画像',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'リンクを開く',
|
||||
'settings.window_target.current' => 'このタブで開く',
|
||||
'settings.window_target.one' => '同じタブで開く',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => '기부',
|
||||
'settings.version' => '버전',
|
||||
'settings.background_image' => '배경 이미지',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => '다음에서 링크 열기',
|
||||
'settings.window_target.current' => '현재 탭에서 열기',
|
||||
'settings.window_target.one' => '같은 탭에서 열기',
|
||||
|
||||
@@ -30,6 +30,10 @@ return [
|
||||
|
||||
'settings.background_image' => 'Imagin dedree',
|
||||
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
|
||||
'settings.window_target' => 'I link se derven...',
|
||||
|
||||
'settings.window_target.current' => 'In quella scheda chi',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Doneren',
|
||||
'settings.version' => 'Versie',
|
||||
'settings.background_image' => 'Achtergrondafbeelding',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link opent in',
|
||||
'settings.window_target.current' => 'In de huidige tab openen',
|
||||
'settings.window_target.one' => 'In dezelfde tab openen',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Donere',
|
||||
'settings.version' => 'Versjon',
|
||||
'settings.background_image' => 'Bakgrunnsbilde',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link åpnes inn',
|
||||
'settings.window_target.current' => 'Åpne i denne fanen',
|
||||
'settings.window_target.one' => 'Åpne i samme fane',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Podarować',
|
||||
'settings.version' => 'Wersja',
|
||||
'settings.background_image' => 'Tapeta Pulpitu',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Link otwiera się w',
|
||||
'settings.window_target.current' => 'Otwórz w tej zakładce',
|
||||
'settings.window_target.one' => 'Otwórz w tej samej zakładce',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Doar',
|
||||
'settings.version' => 'Versão',
|
||||
'settings.background_image' => 'Imagem de fundo',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'O link abre em',
|
||||
'settings.window_target.current' => 'Abrir neste separador',
|
||||
'settings.window_target.one' => 'Abrir no mesmo separador',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Пожертвования',
|
||||
'settings.version' => 'Версия',
|
||||
'settings.background_image' => 'Фоновое изображение',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Открывать ссылки в',
|
||||
'settings.window_target.current' => 'Открывать в этой же закладке',
|
||||
'settings.window_target.one' => 'Открывать в той же закладке',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Doniraj',
|
||||
'settings.version' => 'Verzija',
|
||||
'settings.background_image' => 'Slika za ozadje',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Povezava se odpre v',
|
||||
'settings.window_target.current' => 'Odpri v tem zavihku',
|
||||
'settings.window_target.one' => 'Odpri v istem zavihku',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Donera',
|
||||
'settings.version' => 'Version',
|
||||
'settings.background_image' => 'Bakgrundsbild',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Länken öppnas i',
|
||||
'settings.window_target.current' => 'Öppna i denna flik',
|
||||
'settings.window_target.one' => 'Öppna i samma flik',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Bağış yapmak',
|
||||
'settings.version' => 'Versiyon',
|
||||
'settings.background_image' => 'Arkaplan Resmi',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Bağlantı açılır',
|
||||
'settings.window_target.current' => 'Bu sekmede aç',
|
||||
'settings.window_target.one' => 'Aynı sekmede aç',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => 'Пожертви',
|
||||
'settings.version' => 'Версія',
|
||||
'settings.background_image' => 'Фонове зображення',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => 'Відкривати посилання в',
|
||||
'settings.window_target.current' => 'Відкривати в цій вкладці',
|
||||
'settings.window_target.one' => 'Відкривати у тій самій вкладці',
|
||||
|
||||
@@ -19,6 +19,8 @@ return [
|
||||
|
||||
'settings.version' => '版本',
|
||||
'settings.background_image' => '背景图片',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => '链接打开方式',
|
||||
'settings.window_target.current' => '在当前选项卡中打开',
|
||||
'settings.window_target.one' => '在同一个选项卡中打开',
|
||||
|
||||
@@ -9,6 +9,8 @@ return array (
|
||||
'settings.donate' => '捐赠',
|
||||
'settings.version' => '版本',
|
||||
'settings.background_image' => '背景图片',
|
||||
'settings.trianglify' => 'Trianglify',
|
||||
'settings.trianglify_seed' => 'Trianglify Random Seed',
|
||||
'settings.window_target' => '链接打开方式',
|
||||
'settings.window_target.current' => '在当前选项卡中打开',
|
||||
'settings.window_target.one' => '在同一个选项卡中打开',
|
||||
|
||||
@@ -116,6 +116,34 @@
|
||||
</div>
|
||||
<script src="{{ asset('js/jquery.min.js') }}"></script>
|
||||
<script src="{{ asset(mix('js/app.js')) }}"></script>
|
||||
@if($trianglify == 'true')
|
||||
<script src="{{ asset('js/trianglify.js') }}"></script>
|
||||
<script>
|
||||
function addTriangleTo(target) {
|
||||
var dimensions = target.getClientRects()[0];
|
||||
var pattern = Trianglify({
|
||||
width: dimensions.width,
|
||||
height: dimensions.height
|
||||
@if($trianglify_seed <> '')
|
||||
, seed: '{!! $trianglify_seed !!}'
|
||||
@endif
|
||||
});
|
||||
target.style['background-image'] = 'url(' + pattern.png() + ')';
|
||||
target.style['background-size'] = 'cover';
|
||||
target.style['-webkit-background-size'] = 'cover';
|
||||
target.style['-moz-background-size'] = 'cover';
|
||||
target.style['-o-background-size'] = 'cover';
|
||||
}
|
||||
var resizeTimer;
|
||||
$(window).on('resize', function(e) {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(function() {
|
||||
addTriangleTo(app);
|
||||
}, 400);
|
||||
});
|
||||
</script>
|
||||
<script>addTriangleTo(app);</script>
|
||||
@endif
|
||||
@yield('scripts')
|
||||
|
||||
<script id="custom_js">
|
||||
|
||||
@@ -106,7 +106,7 @@ Route::group([
|
||||
Route::patch('edit/{id}', [SettingsController::class,'update']);
|
||||
});
|
||||
|
||||
Auth::routes();
|
||||
Auth::routes(['register' => false]);
|
||||
|
||||
Route::get('/home', [HomeController::class,'index'])->name('home');
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -22,6 +22,8 @@ class SettingsTest extends TestCase
|
||||
'Support',
|
||||
'Donate',
|
||||
'Background Image',
|
||||
'Trianglify',
|
||||
'Trianglify Random Seed',
|
||||
'Homepage Search',
|
||||
'Default Search Provider',
|
||||
'Link opens in',
|
||||
|
||||
42
tests/Unit/helpers/IsImageTest.php
Normal file
42
tests/Unit/helpers/IsImageTest.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\helpers;
|
||||
|
||||
use Tests\TestCase;
|
||||
|
||||
class IsImageTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function test_returns_true_when_file_is_image()
|
||||
{
|
||||
$file = file_get_contents(__DIR__ . '/fixtures/heimdall-icon-small.png');
|
||||
|
||||
$actual = isImage($file, 'png');
|
||||
|
||||
$this->assertTrue($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function test_returns_false_when_file_extension_is_image_but_content_is_not()
|
||||
{
|
||||
$actual = isImage("<?php ?>", "png");
|
||||
|
||||
$this->assertFalse($actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function test_returns_false_when_file_extension_is_not_image_but_content_is()
|
||||
{
|
||||
$file = file_get_contents(__DIR__ . '/fixtures/heimdall-icon-small.png');
|
||||
|
||||
$actual = isImage($file, 'php');
|
||||
|
||||
$this->assertFalse($actual);
|
||||
}
|
||||
}
|
||||
BIN
tests/Unit/helpers/fixtures/heimdall-icon-small.png
Normal file
BIN
tests/Unit/helpers/fixtures/heimdall-icon-small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Reference in New Issue
Block a user