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
2 changes: 1 addition & 1 deletion KNOWLEDGE_BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ Sources: [follow import](app/Actions/CreateUserGitHubFollows.php), [suggestions]

Logs are the app's timelines. **Following** contains your commits and those of developers you follow, newest first; it requires sign-in. **Latest** contains the newest public commits across the app. **Trending** favors recent public commits that attract engagement from distinct other developers across the thread, with replies and quotes weighing more than stars and diminishing returns from additional engagement. Pastéis don't affect Trending. On the web, Trending reshuffles each time you open it: higher-scoring commits are more likely to appear first, but the order varies between visits and the same draw is used while you scroll. The signed API does not redraw on each visit.

Logs list top-level commits, including quotes, rather than every reply, 20 at a time as you scroll, and show your own pending commits to you. Following and Latest check for new commits every 30 seconds and mark where you left off. The new-commit control previews up to five distinct authors, with a +N badge for additional authors. Following loads the new commits when you select it. Latest loads new commits automatically: at the top they animate into view, while a reader who has scrolled keeps their place and can scroll up to see them. On touch screens, swipe sideways to move between logs. An empty Following log suggests three recent commits from people to follow. Muted and blocked people are filtered for signed-in viewers. The last log you opened is remembered.
Logs list top-level commits, including quotes, rather than every reply, 20 at a time as you scroll, and show your own pending commits to you. Following and Latest check for new commits every 30 seconds and mark where you left off. Following and Latest load new commits automatically. At the top, they animate into view without a notification. If you have scrolled down, your reading position stays still and a **New commits** control appears only after new commits are loaded above you. It previews up to three distinct authors from the new commits waiting above you, with a +N circle for additional authors. Each check removes deleted or no-longer-visible arrivals from the announcement and loaded feed; the control disappears if none remain. Select it to scroll to the new commits; it disappears when you reach them. On touch screens, swipe sideways to move between logs. An empty Following log suggests three recent commits from people to follow. Muted and blocked people are filtered for signed-in viewers. The last log you opened is remembered.

Browser Back and Forward restore expanded replies and loaded thread continuations. Offscreen commits are measured before scroll restoration so returning to a log or discussion keeps the content in place.

Expand Down
6 changes: 1 addition & 5 deletions app/Http/Controllers/LogController.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,7 @@ public function show(ShowLogRequest $request, #[CurrentUser] ?User $user, Log $l

return $seen instanceof Commit ? $latest->count($log, $user, $seen) : 0;
}),
'newCommitAuthors' => Inertia::optional(function () use ($request, $user, $log, $latest): array {
$seen = $request->since();

return $seen instanceof Commit ? $latest->authors($log, $user, $seen) : ['users' => [], 'total' => 0];
}),
'removedCommitIds' => Inertia::optional(fn (): array => $latest->missing($log, $user, $request->pending())),
'suggestions' => fn (): Collection => $user instanceof User && $log === Log::Following && ! $user->following()->exists()
? $suggested->get($user)
: new Collection(),
Expand Down
13 changes: 13 additions & 0 deletions app/Http/Requests/ShowLogRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public function rules(): array
return [
'since' => ['nullable', 'uuid'],
'through' => ['nullable', 'uuid'],
'pending' => ['sometimes', 'array', 'list'],
'pending.*' => ['required', 'uuid', 'distinct'],
];
}

Expand All @@ -45,6 +47,17 @@ public function since(): ?Commit
: null;
}

/**
* @return list<string>
*/
public function pending(): array
{
/** @var list<string> $pending */
$pending = $this->validated('pending', []);

return $pending;
}

public function prepareForValidation(): void
{
$this->merge(['through' => $this->header('X-Log-Through')]);
Expand Down
19 changes: 7 additions & 12 deletions app/Queries/LatestLogCommitsQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use App\Enums\Log;
use App\Models\Commit;
use App\Models\User;
use Illuminate\Support\Collection;

/**
* A ranked log does not put new commits on top, so it does not offer them either: they belong to the Latest log. The
Expand All @@ -28,21 +27,17 @@ public function count(Log $log, ?User $user, Commit $since): int
}

/**
* @return array{users: Collection<int, User>, total: int}
* @param list<string> $pending
* @return list<string>
*/
public function authors(Log $log, ?User $user, Commit $since): array
public function missing(Log $log, ?User $user, array $pending): array
{
if ($log->isRanked()) {
return ['users' => collect(), 'total' => 0];
if ($pending === [] || $log->isRanked()) {
return [];
}

$query = $log->query()->builder($user)
->newerThan($since)
->when($user, fn (CommitBuilder $query, User $user): CommitBuilder => $query->where($query->qualifyColumn('user_id'), '!=', $user->id))
->reorder()->toBase();
$total = (clone $query)->distinct()->count('commits.user_id');
$ids = $query->select('commits.user_id')->distinct()->orderBy('commits.user_id')->limit(5)->pluck('user_id');
$visible = $log->query()->builder($user)->whereKey($pending)->toBase()->select('commits.id')->reorder()->pluck('commits.id');

return ['users' => User::query()->whereIn('id', $ids)->orderBy('id')->get()->toBase(), 'total' => $total];
return array_values(collect($pending)->reject(fn (string $id): bool => $visible->contains($id))->all());
}
}
Loading
Loading