use axum::extract::{Path, State}; use axum::response::Response; use maud::html; use models::common::watch_mode::WatchMode; 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/watch-button", tag = "html", description = "渲染关注按钮、当前模式和关注者人数片段。", operation_id = "render_watch_button", params(HtmlRepoPath), responses( (status = 200, description = "watch button html fragment", content_type = "text/html"), (status = 404, description = "repo not found") ) )] pub async fn render_watch_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 watch_mode = match ctx.uid { Some(uid) => service .get_watch_mode(&ctx.ctx, uid) .await .unwrap_or_default() .unwrap_or(WatchMode::Unwatched), None => WatchMode::Unwatched, }; let is_watching = watch_mode == WatchMode::Watching; let base = "git-watch-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 watch_count = ctx.dto.watchers_count; let mode_text = match watch_mode { WatchMode::Watching => "Watching", WatchMode::Unwatched => "Not watching", WatchMode::Ignore => "Ignoring", }; let markup = html! { div class=(cls) data-component="git-watch-button" data-space=(space) data-repo=(repo) data-watching=(if is_watching { "true" } else { "false" }) data-mode=(format!("{watch_mode:?}").to_lowercase()) data-count=(watch_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="change-watch" { 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 9.5a1.5 1.5 0 100-3 1.5 1.5 0 000 3z" {} path d="M1.5 8s2.5-5.5 6.5-5.5S14.5 8 14.5 8s-2.5 5.5-6.5 5.5S1.5 8 1.5 8zM8 12c2.5 0 4.5-2.5 4.5-4S10.5 4 8 4 3.5 6.5 3.5 8s2 4 4.5 4z" {} } span { (mode_text) } } 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}/watchers")) title=(format!("{watch_count} watchers")) { (watch_count) } } }; response_html(markup, 30) }