summaryrefslogtreecommitdiff
path: root/layouts/_partials/posts/action-menu/like-button.html
blob: c9e793b80bd3c947b916201cb80a6b6add0f1780 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
{{ $pageID := .File.UniqueID | urlize }}
<!-- 点赞按钮 -->
<div class="relative" id="like-container-{{ $pageID }}">
  <button class="dark:invert flex items-center justify-center gap-1.5 min-w-12 h-12 px-2
      border-none bg-transparent text-gray-600 cursor-pointer relative transition-all duration-200
      hover:bg-black/5 hover:rounded-lg group animate-count-infinite"
      onclick="sendLike('{{ $pageID }}')"
      id="like-btn-{{ $pageID }}"
      title="{{ T "actionMenu.like" }}"
      data-liked-title="{{ T "actionMenu.liked" }}"
      data-tooltip>
    <img src="/img/heart-organ.svg" width="20" height="20"
        alt="{{ T "actionMenu.like" }}"
        class="brightness-40 flex-shrink-0 transition-all duration-300 dark:brightness-70 dark:contrast-120" id="like-icon-{{ $pageID }}" />
    <span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" id="like-count-{{ $pageID }}">...</span>
  </button>
</div>

<style>
.liked-heart {
  filter: brightness(0) saturate(100%) invert(8%) sepia(100%) saturate(7500%) hue-rotate(0deg) brightness(70%) contrast(150%) !important;
}

.liked-count {
  color: #8B0000 !important;
}
</style>

<script>
document.addEventListener('DOMContentLoaded', () => {
  // get page ID to fetch and update like data
  const pageId = "{{ $pageID }}";

  // get required elements
  const elements = {
    count: document.getElementById("like-count-" + pageId),
    btn: document.getElementById("like-btn-" + pageId),
    container: document.getElementById("like-container-" + pageId),
    icon: document.getElementById("like-icon-" + pageId)
  };

  // return if no page ID found or not in production or no elements
  if (
    !pageId || window.location.host !== 'www.geedea.pro' ||
    !elements.count || !elements.btn || !elements.container
  ) return;

  function setLikedState() {
    // update classes
    elements.icon?.classList.add('liked-heart');
    elements.icon?.classList.add('animate-heart-beat');
    elements.count?.classList.add('liked-count');
    elements.btn.disabled = true;
    elements.container.classList.add('liked');
    // update tooltip
    elements.btn.setAttribute('title',
      elements.container.classList.contains('liked')
        ? elements.btn.getAttribute('data-liked-title')
        : '为这篇文章献上心脏'
    );
  }

  async function fetchLikes() {
    try {
      const response = await fetch("https://like.guhub.cn/like/" + pageId);
      const data = await response.json();
      elements.count.innerText = data.likes ?? 0;
      if (localStorage.getItem("liked_" + pageId)) {
        setLikedState();
        updateOrganFarm(data.likes);
      }
    } catch(e) {
      console.log(e);
      elements.count.innerText = "❌";
    }
  }

  window.sendLike = async function(pageId) {
    if (localStorage.getItem("liked_" + pageId)) return;

    try {
      const response = await fetch("https://like.guhub.cn/like/" + pageId, { method: "POST" });
      const data = await response.json();
      localStorage.setItem("liked_" + pageId, "1");
      elements.count.innerText = data.likes ?? 1;
      updateOrganFarm(data.likes);
      setLikedState();
    } catch(e) {
      console.log(e);
      alert("点赞失败,请稍后再试");
    }
  };

  function updateOrganFarm(count) {
    const organFarm = document.getElementById("organ-farm");
    const organCount = count || parseInt(elements.count.innerText);
    const organImages = [
      "https://image.guhub.cn/picgo2025/oragn-3.png",
      "https://image.guhub.cn/picgo2025/organ-1.png",
      "https://image.guhub.cn/picgo2025/organ-2.png"
    ];

    if (!organFarm) return;
    if (organFarm.classList.contains("hidden")) {
      organFarm.classList.remove("hidden");
      organFarm.classList.add("animate-slide-in-down");
    }

    organFarm.innerHTML = "";
    for (let i = 0; i < organCount; i++) {
      const img = document.createElement("img");
      img.className = "transition hover:scale-150 dark:invert";

      const sizeRange = [6, 10];
      const size = Math.floor(Math.random() * (sizeRange[1] - sizeRange[0] + 1)) + sizeRange[0];
      img.classList.add(`w-${size}`, `h-${size}`);

      img.src = organImages[Math.floor(Math.random() * organImages.length)];
      // randomly offset and rotate
      img.classList.add("rotate-" + Math.floor(Math.random() * 5));
      img.classList.add("translate-x-" + Math.floor(Math.random() * 5));
      img.classList.add("translate-y-" + Math.floor(Math.random() * 5));
      img.classList.add("opacity" + (100 - Math.floor(Math.random() * 3)*10));

      organFarm.appendChild(img);
    }
  }

  // fetch likes when action menu is visible
  const observer = new IntersectionObserver((entries, obs) => {
    if (entries[0].isIntersecting) {
      fetchLikes();
      obs.disconnect();
    }
  });
  observer.observe(document.getElementById("action-menu"));
});
</script>