use export::http::{Path, Response, State}; use maud::html; use crate::handler::html::{HtmlRepoPath, archived_class, resolve, response_html}; use crate::service::GitService; use crate::share::access::BasicAuth; #[utoipa::path( get, path = "/repos/{space_name}/{repo_name}/html/star-button", tag = "html", description = "渲染当前用户视角的加星按钮与星数片段。", operation_id = "render_star_button", params(HtmlRepoPath), responses( (status = 200, description = "star button html fragment", content_type = "text/html"), (status = 404, description = "repo not found") ) )] pub async fn render_star_button( State(service): State, Path(path): Path, auth: BasicAuth, ) -> Response { let ctx = match resolve(service.clone(), path, auth).await { Ok(c) => c, Err(resp) => return resp, }; let is_starred = match ctx.uid { Some(uid) => service.is_starred(&ctx.ctx, uid).await.unwrap_or(false), None => false, }; let base = "git-star-button inline-flex items-center rounded-md border border-zinc-200 bg-white text-xs text-zinc-700 shadow-sm"; let cls = archived_class(&ctx.dto, base); let space = ctx.space_name.clone(); let repo = ctx.repo_name.clone(); let star_count = ctx.dto.stars_count; let markup = html! { div class=(cls) data-component="git-star-button" data-space=(space) data-repo=(repo) data-starred=(if is_starred { "true" } else { "false" }) data-count=(star_count) data-archived=(if ctx.dto.is_archived { "true" } else { "false" }) { button class="flex items-center gap-1.5 px-2.5 py-1 font-medium hover:bg-zinc-50 border-r border-zinc-200 transition-colors" type="button" data-action="toggle-star" { @if is_starred { svg class="h-3.5 w-3.5 text-amber-500 fill-amber-500" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg" { path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z" {} } span { "Starred" } } @else { svg class="h-3.5 w-3.5 text-zinc-500" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg" { path d="M8 .25a.75.75 0 01.673.418l1.882 3.815 4.21.612a.75.75 0 01.416 1.279l-3.046 2.97.719 4.192a.75.75 0 01-1.088.791L8 12.347l-3.766 1.98a.75.75 0 01-1.088-.79l.72-4.194L.818 6.374a.75.75 0 01.416-1.28l4.21-.611L7.327.668A.75.75 0 018 .25z" {} } span { "Star" } } } a class="px-2.5 py-1 font-mono text-[11px] text-zinc-600 hover:text-zinc-900 hover:bg-zinc-50 transition-colors" href=(format!("/{space}/{repo}/stargazers")) title=(format!("{star_count} stargazers")) { (star_count) } } }; response_html(markup, 30) }