Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions app/Devnull/Account.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,13 @@ public function rememberUnreadRemotes(int $count): void
}

/**
* Signs this phone out: who it was, the badges, its pastéis and Remotes, every answer kept for a quick start,
* and your unsent drafts.
* Signs this phone out: who it was, the badges, its pastéis and Remotes, every answer and image kept for a
* quick start, and your unsent drafts.
*/
public function forget(): void
{
app(ResponseCache::class)->flush();
ImageCache::clear();
app(Stash::class)->forget($this->user()?->id);
app(Outbox::class)->forgetAll($this->user()?->id);

Expand Down
5 changes: 5 additions & 0 deletions app/Devnull/DownloadImages.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ public static function save(array $urls, ?float $until = null): int
$batch,
));

// Signing out empties the cache (see Account::forget), and this thread can't tell it happened otherwise.
if (app(Account::class)->user() === null) {
break;
}

foreach ($batch as $index => $url) {
$response = $responses[$index] ?? null;

Expand Down
13 changes: 13 additions & 0 deletions app/Devnull/ImageCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Devnull;

use Carbon\CarbonImmutable;
use Illuminate\Support\Facades\File;

/**
* Remote images kept on the device: avatars, commit images and link preview
Expand Down Expand Up @@ -117,6 +118,18 @@ public static function takePrune(): ?int
return $cache->startedAt - self::hours() * 3600;
}

/**
* Deletes every image on the device, on sign-out, so the next person to
* sign in never sees what the last one was shown. What's drawn from now on
* comes from its URL.
*/
public static function clear(): void
{
File::deleteDirectory(self::directory());

app(self::class)->sources = [];
}

/**
* Every image URL in an answer, wherever it's nested: people's avatars,
* commits' images and link previews' images.
Expand Down
24 changes: 24 additions & 0 deletions tests/Feature/ImageCacheTest.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php

use App\Devnull\Account;
use App\Devnull\Client;
use App\Devnull\DownloadImages;
use App\Devnull\FetchInBackground;
Expand Down Expand Up @@ -143,6 +144,7 @@ function imagesQueued(): array
});

it('keeps only what downloads as an image, and clears out images older than a day when asked to', function () {
signIn();
$stale = cachedImage('https://avatars.githubusercontent.com/u/8?v=4', hoursAgo: 30);
File::put(ImageCache::path('https://avatars.githubusercontent.com/u/9?v=4').'.part', 'half');

Expand Down Expand Up @@ -253,6 +255,7 @@ function imagesQueued(): array
});

it('brings an answer\'s images down with it when asked, before it comes back', function () {
signIn();
Http::fake([
'avatars.githubusercontent.com/*' => Http::response('png bytes', 200, ['Content-Type' => 'image/png']),
'devnull.test/api/v1/log/following*' => Http::response(pageJson([commitJson(['author' => userJson(['avatar_url' => 'https://avatars.githubusercontent.com/u/2?v=4'])])])),
Expand All @@ -275,7 +278,28 @@ function imagesQueued(): array
expect(File::exists(ImageCache::path('https://avatars.githubusercontent.com/u/3?v=4')))->toBeFalse();
});

it('empties the image folder on sign-out, and draws what it held from the URL again', function () {
signIn();
$url = 'https://avatars.githubusercontent.com/u/2?v=4';
$path = cachedImage($url);

expect(ImageCache::src($url))->toBe($path);

app(Account::class)->forget();

expect(File::isDirectory(ImageCache::directory()))->toBeFalse()
->and(ImageCache::src($url))->toBe($url);
});

it('keeps no image that lands once nobody is signed in', function () {
Http::fake(['avatars.githubusercontent.com/*' => Http::response('png bytes', 200, ['Content-Type' => 'image/png'])]);

expect(DownloadImages::save(['https://avatars.githubusercontent.com/u/2?v=4']))->toBe(0)
->and(File::exists(ImageCache::path('https://avatars.githubusercontent.com/u/2?v=4')))->toBeFalse();
});

it('gives images it waits on only the time that is left, and starts none once it is up', function () {
signIn();
Http::fake(['avatars.githubusercontent.com/*' => Http::response('png bytes', 200, ['Content-Type' => 'image/png'])]);

expect(DownloadImages::save(['https://avatars.githubusercontent.com/u/2?v=4'], until: microtime(true) - 1))->toBe(0);
Expand Down
Loading