1
0
mirror of https://github.com/Kovah/LinkAce.git synced 2025-01-17 21:28:30 +01:00

Add version information and update check to footer (#220)

This commit is contained in:
Kovah 2021-02-26 23:22:15 +01:00
parent 3d9a6c638d
commit a217d21a34
No known key found for this signature in database
GPG Key ID: AAAA031BA9830D7B
12 changed files with 99 additions and 84 deletions

View File

@ -3,7 +3,10 @@
namespace App\Helper; namespace App\Helper;
use Composer\Semver\Comparator; use Composer\Semver\Comparator;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
/** /**
* Class UpdateHelper * Class UpdateHelper
@ -14,17 +17,37 @@ class UpdateHelper
{ {
protected static $releaseApiUrl = 'https://api.github.com/repos/kovah/linkace/releases'; protected static $releaseApiUrl = 'https://api.github.com/repos/kovah/linkace/releases';
/**
* Get the current version from the package.json file and cache it for a day.
*
* @return mixed
*/
public static function currentVersion()
{
return Cache::remember('current-version', 86400, function () {
try {
$package = json_decode(Storage::disk('root')->get('package.json'), false);
} catch (Exception $e) {
return null;
}
return isset($package->version) ? 'v' . $package->version : null;
});
}
/** /**
* Returns the version string if there is a newer version is available. * Returns the version string if there is a newer version is available.
* Returns true if the check was successful, but no updates was found. * Returns true if the check was successful, but no updates was found.
* Returns false if the check could not be executed, e.g. due to network * Returns false if the check could not be executed, e.g. due to network
* issues. * issues.
* *
* @param bool $cacheResult
* @return bool|string * @return bool|string
*/ */
public static function checkForUpdates() public static function checkForUpdates(bool $cacheResult = false)
{ {
$currentVersion = getVersionFromPackage(); return Cache::remember('updatecheck', $cacheResult ? 86400 : 0, function () {
$currentVersion = self::currentVersion();
$latestVersion = self::getCurrentVersionFromAPI(); $latestVersion = self::getCurrentVersionFromAPI();
if ($latestVersion === null) { if ($latestVersion === null) {
@ -36,6 +59,7 @@ class UpdateHelper
} }
return true; return true;
});
} }
/** /**

View File

@ -207,22 +207,6 @@ function linkTarget(): string
return usersettings('links_new_tab') ? $newTab : ''; return usersettings('links_new_tab') ? $newTab : '';
} }
/**
* Get the current version from the package.json file
*
* @return string|null
*/
function getVersionFromPackage(): ?string
{
try {
$package = json_decode(Storage::disk('root')->get('package.json'), false);
} catch (Exception $e) {
return null;
}
return isset($package->version) ? 'v' . $package->version : null;
}
/** /**
* Properly escape symbols used in search queries. * Properly escape symbols used in search queries.
* *

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers\App; namespace App\Http\Controllers\App;
use App\Helper\UpdateHelper;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\SystemSettingsUpdateRequest; use App\Http\Requests\SystemSettingsUpdateRequest;
use App\Models\Setting; use App\Models\Setting;
@ -22,7 +23,7 @@ class SystemSettingsController extends Controller
public function getSystemSettings(): View public function getSystemSettings(): View
{ {
return view('actions.settings.system', [ return view('actions.settings.system', [
'linkaceVersion' => getVersionFromPackage(), 'linkaceVersion' => UpdateHelper::currentVersion(),
]); ]);
} }

View File

@ -17,12 +17,10 @@ export default class UpdateCheck {
} }
init () { init () {
debounce(() => {
this.checkForUpdate().then(result => { this.checkForUpdate().then(result => {
this.result = result; this.result = result;
this.updateCheckStatus(); this.updateCheckStatus();
}); });
}, 500);
} }
updateCheckStatus () { updateCheckStatus () {

View File

@ -9,10 +9,8 @@ export default class UrlField {
this.$field.addEventListener('keyup', this.onKeyup.bind(this)); this.$field.addEventListener('keyup', this.onKeyup.bind(this));
this.tagSuggestions = getInstance( const $tags = document.querySelector('#tags');
document.querySelector('#tags'), this.tagSuggestions = $tags ? getInstance($tags, TagsSelect) : null;
TagsSelect
);
} }
onKeyup () { onKeyup () {

View File

@ -28,7 +28,7 @@ xdebug.scream = 0
xdebug.cli_color = 1 xdebug.cli_color = 1
xdebug.show_local_vars = 1 xdebug.show_local_vars = 1
xdebug.mode = profile xdebug.mode = off
xdebug.profiler_enable = 0 xdebug.profiler_enable = 0
xdebug.profiler_enable_trigger=1 xdebug.profiler_enable_trigger=1
xdebug.profiler_enable_trigger_value=1 xdebug.profiler_enable_trigger_value=1

View File

@ -2,14 +2,8 @@
<div class="card-header"> <div class="card-header">
@lang('settings.update_check') @lang('settings.update_check')
</div> </div>
<div class="update-check card-body small" data-current-version="{{ $linkaceVersion }}"> <div class="card-body small" >
<p>@lang('linkace.version', ['version' => $linkaceVersion])</p> <p>@lang('linkace.version', ['version' => $linkaceVersion])</p>
<x-update-check/>
<div class="update-check-running">@lang('settings.update_check_running')</div>
<div class="update-check-version-found text-success d-none">@lang('settings.update_check_version_found')</div>
<div class="update-check-success d-none">@lang('settings.update_check_success')</div>
<div class="update-check-failed text-danger d-none">@lang('settings.update_check_failed')</div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,6 @@
<div {{ $attributes->merge(['class' => 'update-check']) }} data-current-version="{{ \App\Helper\UpdateHelper::currentVersion() }}">
<div class="update-check-running">@lang('settings.update_check_running')</div>
<div class="update-check-version-found text-success d-none">@lang('settings.update_check_version_found')</div>
<div class="update-check-success d-none">@lang('settings.update_check_success')</div>
<div class="update-check-failed text-danger d-none">@lang('settings.update_check_failed')</div>
</div>

View File

@ -1,3 +1,8 @@
<aside class="footer container text-center small pt-3 pb-5"> <aside class="footer container text-center small pt-3 pb-5">
<div>
@lang('linkace.project_of') <a href="https://www.kovah.de/?utm_source=linkace" rel="noopener" target="_blank">Kovah.de</a> @lang('linkace.project_of') <a href="https://www.kovah.de/?utm_source=linkace" rel="noopener" target="_blank">Kovah.de</a>
</div>
<div class="mt-1">
@lang('linkace.version', ['version' => \App\Helper\UpdateHelper::currentVersion()]) - <x-update-check class="d-inline-block"/>
</div>
</aside> </aside>

View File

@ -136,31 +136,4 @@ class HelperFunctionsTest extends TestCase
$this->assertNull($link); $this->assertNull($link);
} }
public function testVersionFromPackage(): void
{
Storage::fake('root')->put('package.json', '{"version":"0.0.39"}');
$version = getVersionFromPackage();
$this->assertEquals('v0.0.39', $version);
}
public function testVersionFromPackageWithInvalidFile(): void
{
Storage::fake('root')->put('package.json', '{"foo":"bar"}');
$version = getVersionFromPackage(); // should now return null because there is no version field
$this->assertNull($version);
}
public function testVersionFromPackageWithMissingFile(): void
{
Storage::fake('root');
$version = getVersionFromPackage(); // should now return null because there is no package.json
$this->assertNull($version);
}
} }

View File

@ -4,15 +4,14 @@ namespace Tests\Helper;
use App\Helper\UpdateHelper; use App\Helper\UpdateHelper;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase; use Tests\TestCase;
class UpdateCheckTest extends TestCase class UpdateCheckTest extends TestCase
{ {
/** /*
* Test the checkForUpdates() helper function with a new update available. * Test the checkForUpdates() helper function with a new update available.
* Must return the given version string. * Must return the given version string.
*
* @return void
*/ */
public function testSuccessfulCheck(): void public function testSuccessfulCheck(): void
{ {
@ -28,11 +27,9 @@ class UpdateCheckTest extends TestCase
$this->assertEquals('v100.0.0', $result); $this->assertEquals('v100.0.0', $result);
} }
/** /*
* Test the checkForUpdates() helper function with no update available. * Test the checkForUpdates() helper function with no update available.
* Must return true. * Must return true.
*
* @return void
*/ */
public function testSuccessfulCheckWithoutVersion(): void public function testSuccessfulCheckWithoutVersion(): void
{ {
@ -48,13 +45,11 @@ class UpdateCheckTest extends TestCase
$this->assertTrue($result); $this->assertTrue($result);
} }
/** /*
* Test the checkForUpdates() helper function, but trigger a network / http error. * Test the checkForUpdates() helper function, but trigger a network / http error.
* Must return false. * Must return false.
*
* @return void
*/ */
public function testValidWaybackLink(): void public function testUpdateCheckWithNetworkError(): void
{ {
Http::fake([ Http::fake([
'github.com/*' => Http::response([], 404), 'github.com/*' => Http::response([], 404),
@ -64,4 +59,40 @@ class UpdateCheckTest extends TestCase
$this->assertFalse($result); $this->assertFalse($result);
} }
/*
* Test if the UpdateHelper correctly returns a version from the package.json file.
*/
public function testVersionFromPackage(): void
{
Storage::fake('root')->put('package.json', '{"version":"0.0.39"}');
$version = UpdateHelper::currentVersion();
$this->assertEquals('v0.0.39', $version);
}
/*
* The UpdateHelper should return null if there is no version field.
*/
public function testVersionFromPackageWithInvalidFile(): void
{
Storage::fake('root')->put('package.json', '{"foo":"bar"}');
$version = UpdateHelper::currentVersion();
$this->assertNull($version);
}
/*
* The UpdateHelper should return null if no package.json file was found.
*/
public function testVersionFromPackageWithMissingFile(): void
{
Storage::fake('root');
$version = UpdateHelper::currentVersion();
$this->assertNull($version);
}
} }

1
webpack.mix.js vendored
View File

@ -9,6 +9,7 @@ mix.disableNotifications();
mix.setPublicPath('public'); mix.setPublicPath('public');
mix.js('resources/assets/js/app.js', 'assets/dist/js') mix.js('resources/assets/js/app.js', 'assets/dist/js')
.sourceMaps()
.version(); .version();
mix.combine([ mix.combine([