From 578226ed808c908e4eb8fb4a309db05dca58887e Mon Sep 17 00:00:00 2001 From: sulimanbenhalim Date: Tue, 3 Nov 2026 03:10:18 +0200 Subject: [PATCH] Open an organization's screen from a link to it, as the web does --- app/NativeComponents/Profile.php | 9 +++++++- tests/Feature/Screens/ProfileTest.php | 30 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/app/NativeComponents/Profile.php b/app/NativeComponents/Profile.php index e3c65351..173cad7c 100644 --- a/app/NativeComponents/Profile.php +++ b/app/NativeComponents/Profile.php @@ -680,10 +680,17 @@ protected function showsContent(): bool /** * A profile across a block has its own page, as on the web, whatever devnull's message says. devnull sends who - * you blocked with it, for the page's name and avatar. + * you blocked with it, for the page's name and avatar. A handle no user has may be an organization's, which shares + * its link on the web, so until devnull has sent anything for it, the organization's screen takes this one's place. */ protected function refused(ApiException $exception): bool { + if ($exception->status === 404 && ! $this->commitsLoaded && ($this->profile === null || $this->sketched)) { + $this->replace($this->tabRoot().'/organizations/'.rawurlencode($this->username)); + + return true; + } + if ($exception->is(ErrorCode::UserBlocked)) { if ($exception->user !== null && $exception->user->username === $this->username) { $this->profile = new ProfileData($exception->user); diff --git a/tests/Feature/Screens/ProfileTest.php b/tests/Feature/Screens/ProfileTest.php index ca6b090e..38c88793 100644 --- a/tests/Feature/Screens/ProfileTest.php +++ b/tests/Feature/Screens/ProfileTest.php @@ -1,5 +1,6 @@ assertSet('skeletonFrame', false)->assertSee('Kept Name')->assertSee('Kept commit'); }); + +it("opens an organization's screen in its place when devnull has no user by that handle, as the web does", function (string $tab, Closure $data) { + fakeApi([ + 'GET /api/v1/users/dev-null-sh' => [['message' => 'No query results for model [App\\Models\\User] dev-null-sh'], 404], + 'GET /api/v1/users/dev-null-sh/commits' => [['message' => 'No query results for model [App\\Models\\User] dev-null-sh'], 404], + ]); + + Native::visit("{$tab}/users/dev-null-sh", data: $data())->assertReplacedWith("{$tab}/organizations/dev-null-sh"); +})->with([ + 'a link to it' => ['/log', fn (): array => []], + 'a notification it sent' => ['/notifications', fn (): array => ['user' => User::fromArray(userJson(['handle' => 'dev-null-sh']))]], +]); + +it("stays a person's profile when a thread on it is gone", function (Closure $profile, Closure $data) { + keep('commits/c1/replies', pageJson([])); + fakeApi([ + 'GET /api/v1/users/ada' => $profile(), + 'GET /api/v1/users/ada/commits' => [pageJson([adaCommitJson(['id' => 'c1'])])], + 'GET /api/v1/commits/c1/replies' => [['message' => 'No query results for model [App\\Models\\Commit] c1'], 404], + ]); + + Native::visit('/log/users/ada', data: $data()) + ->call('toggleReplies', 'c1') + ->assertNoNavigation() + ->assertSee('Ada Lovelace'); +})->with([ + 'devnull sent it' => [fn (): array => [profileJson()], fn (): array => []], + "devnull couldn't send it yet" => [fn (): array => [['message' => 'Server Error'], 500], fn (): array => ['user' => User::fromArray(userJson(['handle' => 'ada', 'name' => 'Ada Lovelace']))]], +]);