Skip to content

Commit

Permalink
feat: add moments page (#112)
Browse files Browse the repository at this point in the history
适配[瞬间插件](https://github.com/halo-sigs/plugin-moments)。

/kind feature
Fixes #70

<img width="1138" alt="image" src="https://github.com/halo-dev/theme-earth/assets/21301288/6fc9df4b-0fb3-4116-8cb9-2e02242acbcc">
<img width="1036" alt="image" src="https://github.com/halo-dev/theme-earth/assets/21301288/e4d3243b-e35c-41f5-a1d6-86c1ed9d8b85">

```release-note
适配瞬间插件。
```
  • Loading branch information
ruibaby authored Oct 12, 2023
1 parent 98e1f89 commit e3c2d95
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ module.exports = {
env: {
node: true,
},
rules: {
"@typescript-eslint/ban-ts-comment": "off",
},
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"prettier": "^2.8.8",
"prettier-plugin-tailwindcss": "^0.3.0",
"release-it": "^15.11.0",
"sass": "^1.69.3",
"tailwindcss": "^3.3.2",
"tailwindcss-plugin-icons": "^2.1.1",
"typescript": "^4.9.5",
Expand Down
22 changes: 20 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 8 additions & 8 deletions src/alpine-data/post-upvote.ts → src/alpine-data/upvote.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
interface PostUpvote {
interface upvoteState {
upvotedNames: string[];
init(): void;
upvoted(id: string): boolean;
handleUpvote(name: string): void;
}

export default (): PostUpvote => ({
export default (key: string, group: string, plural: string): upvoteState => ({
upvotedNames: [],
init() {
this.upvotedNames = JSON.parse(localStorage.getItem("halo.upvoted.post.names") || "[]");
this.upvotedNames = JSON.parse(localStorage.getItem(`halo.upvoted.${key}.names`) || "[]");
},
upvoted(id: string) {
return this.upvotedNames.includes(id);
Expand All @@ -25,24 +25,24 @@ export default (): PostUpvote => ({

xhr.onload = () => {
this.upvotedNames = [...this.upvotedNames, name];
localStorage.setItem("halo.upvoted.post.names", JSON.stringify(this.upvotedNames));
localStorage.setItem(`halo.upvoted.${key}.names`, JSON.stringify(this.upvotedNames));

const upvoteNode = document.querySelector('[data-upvote-post-name="' + name + '"]');
const upvoteNode = document.querySelector("[data-upvote-" + key + '-name="' + name + '"]');

if (!upvoteNode) {
return;
}

const upvoteCount = parseInt(upvoteNode.textContent || "0");
upvoteNode.textContent = upvoteCount + 1 + " 点赞";
upvoteNode.textContent = upvoteCount + 1 + "";
};
xhr.onerror = function () {
alert("网络请求失败,请稍后再试");
};
xhr.send(
JSON.stringify({
group: "content.halo.run",
plural: "posts",
group: group,
plural: plural,
name: name,
})
);
Expand Down
7 changes: 4 additions & 3 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import "./styles/tailwind.css";
import "./styles/main.css";
import "./styles/main.scss";
import Alpine from "alpinejs";
import * as tocbot from "tocbot";
import dropdown from "./alpine-data/dropdown";
import colorSchemeSwitcher from "./alpine-data/color-scheme-switcher";
import postUpvote from "./alpine-data/post-upvote";
import upvote from "./alpine-data/upvote";

window.Alpine = Alpine;

Alpine.data("dropdown", dropdown);
Alpine.data("colorSchemeSwitcher", colorSchemeSwitcher);
Alpine.data("postUpvote", postUpvote);
// @ts-ignore
Alpine.data("upvote", upvote);

Alpine.start();

Expand Down
9 changes: 9 additions & 0 deletions src/styles/main.css → src/styles/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,12 @@ body {
.is-active-li {
@apply rounded bg-gray-100 dark:bg-slate-600;
}

.moment-content {
.tag {
&::before {
content: "#";
}
@apply rounded bg-gray-100 px-1 py-0.5 text-sm text-gray-900 hover:bg-gray-200 dark:bg-slate-600 dark:text-slate-50 dark:hover:bg-slate-700 dark:hover:text-slate-100;
}
}
4 changes: 2 additions & 2 deletions templates/assets/dist/main.iife.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion templates/assets/dist/style.css

Large diffs are not rendered by default.

180 changes: 180 additions & 0 deletions templates/moments.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
<!DOCTYPE html>
<html
xmlns:th="https://www.thymeleaf.org"
th:replace="~{modules/layout :: html(title = '瞬间 - ' + ${site.title}, hero = null, content = ~{::content}, head = null, footer = null, sidebar = ~{::sidebar}, contentClass = '')}"
>
<th:block th:fragment="content">
<div class="rounded-xl bg-white p-4 dark:bg-slate-800">
<h1 class="mb-9 text-2xl font-medium dark:text-slate-50">瞬间</h1>
<div class="mb-8">
<nav class="flex flex-wrap gap-4" aria-label="Tabs">
<a
th:href="@{/moments}"
class="rounded bg-gray-100 px-1 py-0.5 text-sm text-gray-900 hover:bg-gray-200 dark:bg-slate-600 dark:text-slate-50 dark:hover:bg-slate-700 dark:hover:text-slate-100"
th:classappend="${#lists.isEmpty(param.tag) ? '!bg-gray-200 dark:!bg-slate-700 dark:!text-slate-100 ring-2 ring-gray-300 dark:ring-slate-600' : ''}"
>
<span>全部</span>
</a>
<a
th:each="tag : ${tags}"
th:href="@{|?tag=${tag.name}|}"
class="rounded bg-gray-100 px-1 py-0.5 text-sm text-gray-900 hover:bg-gray-200 dark:bg-slate-600 dark:text-slate-50 dark:hover:bg-slate-700 dark:hover:text-slate-100"
th:classappend="${#lists.contains(param.tag, tag.name) ? '!bg-gray-200 dark:!bg-slate-700 dark:!text-slate-100 ring-2 ring-gray-300 dark:ring-slate-600' : ''}"
>
<span th:text="|#${tag.name}|"></span>
<sup th:text="${tag.momentCount}"></sup>
</a>
</nav>
</div>
<div>
<ul
role="list"
class="divide-y divide-gray-100 dark:divide-slate-700"
x-data="upvote('moment','moment.halo.run','moments')"
>
<li
th:each="moment : ${moments.items}"
th:attr="x-data=|{name:'${moment.metadata.name}',showComment:false}|"
th:with="content=${moment.spec.content}"
class="animated fadeIn flex w-full items-start gap-2 py-5"
>
<img class="h-12 w-12 rounded-full" th:src="${moment.owner.avatar}" th:alt="${moment.owner.displayName}" />
<div class="ml-6" style="width: calc(100% - 4.75rem)">
<div
th:utext="${content.html}"
class="moment-content prose prose-base !max-w-none break-words dark:prose-invert prose-pre:p-0"
></div>
<div
th:unless="${#lists.isEmpty(moment.spec.content.medium)}"
class="moment-media mt-4 grid w-full grid-cols-3 gap-2 sm:w-1/2"
>
<div class="aspect-h-1 aspect-w-1" th:each="media : ${moment.spec.content.medium}">
<img
th:if="${#strings.equals(media.type,'PHOTO')}"
class="transform-gpu rounded-lg object-cover"
th:src="${media.url}"
/>
<div
th:if="${#strings.equals(media.type,'VIDEO')}"
x-data="{openVideoModal:false}"
class="aspect-h-1 aspect-w-1"
>
<video th:src="${media.url}" class="rounded-lg object-cover"></video>
<div
th:if="${#strings.equals(media.type,'VIDEO')}"
class="absolute flex h-full w-full cursor-pointer items-center justify-center rounded-lg bg-gray-50 opacity-50 transition-all hover:opacity-70"
@click="openVideoModal = true"
>
<i class="i-tabler-play !h-7 !w-7"></i>
</div>
<template x-teleport="body">
<div>
<div
class="fixed inset-0 z-50 bg-gray-800/40 opacity-100 backdrop-blur-sm"
aria-hidden="true"
x-show="openVideoModal"
x-transition:enter="ease-in-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="ease-in-out duration-300"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
></div>
<div
class="fixed inset-0 z-50 overflow-y-auto"
tabindex="-1"
x-show="openVideoModal"
x-transition:enter="ease-out duration-200"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave="ease-in duration-100"
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<div class="flex min-h-full flex-col items-center justify-center p-4 text-center sm:p-0">
<div
@click.outside="openVideoModal = false"
class="relative my-4 transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:w-full sm:max-w-xl"
>
<video th:src="${media.url}" class="w-full" controls></video>
</div>
<div>
<div
@click="openVideoModal = false"
class="group inline-flex items-center justify-center rounded-full bg-white p-1.5"
>
<i class="i-tabler-x block text-gray-600 group-hover:text-gray-900"></i>
</div>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</div>
<div class="mt-3 flex items-center gap-4">
<div
class="inline-flex cursor-pointer items-center text-sm text-gray-400 transition-all hover:text-red-700 dark:text-slate-400 dark:hover:text-red-700"
x-bind:class="{'!text-red-700': upvoted(name)}"
@click="handleUpvote(name)"
>
<i x-show="upvoted(name)" class="i-tabler-heart-filled h-3 w-3"></i>
<i x-show="!upvoted(name)" class="i-tabler-heart h-3 w-3"></i>
<span
class="ml-1"
th:attr="data-upvote-moment-name=${moment.metadata.name}"
th:text="${moment.stats.upvote}"
>
</span>
</div>
<div
class="inline-flex cursor-pointer items-center text-sm text-gray-400 transition-all hover:text-black dark:text-slate-400 dark:hover:text-slate-300"
:class="{'!text-black dark:!text-slate-300':showComment}"
x-on:click="showComment = !showComment"
>
<i class="i-tabler-message-circle h-3 w-3"></i>
<span class="ml-1" th:text="${moment.stats.approvedComment}"> </span>
</div>
<div class="inline-flex items-center text-sm text-gray-400 transition-all dark:text-slate-400">
<i class="i-tabler-calendar h-3 w-3"></i>
<span class="ml-1" th:text="${#dates.format(moment.spec.releaseTime,'yyyy-MM-dd')}"> </span>
</div>
</div>

<div class="mt-2" x-show="showComment">
<halo:comment
group="moment.halo.run"
kind="Moment"
th:attr="name=${moment.metadata.name}"
colorScheme="window.main.currentColorScheme"
/>
</div>
</div>
</li>
</ul>
</div>

<div class="mt-6 flex items-center justify-between" th:if="${moments.hasPrevious() || moments.hasNext()}">
<a
th:href="@{${moments.prevUrl}}"
class="whitespace-no-wrap group inline-flex items-center justify-center gap-1 rounded-md border border-gray-200 bg-white px-4 py-1 text-sm font-medium leading-6 text-gray-600 shadow-sm hover:bg-gray-50 focus:shadow-none focus:outline-none dark:border-slate-600 dark:bg-slate-700 dark:text-slate-100 dark:hover:bg-slate-600 dark:hover:text-white"
>
<span class="i-tabler-arrow-left text-lg transition-all group-hover:-translate-x-1"></span>
<span>上一页</span>
</a>
<span
class="text-sm text-gray-900 dark:text-slate-50"
th:text="|${moments.page} / ${moments.totalPages}|"
></span>
<a
th:href="@{${moments.nextUrl}}"
class="whitespace-no-wrap group inline-flex items-center justify-center gap-1 rounded-md border border-gray-200 bg-white px-4 py-1 text-sm font-medium leading-6 text-gray-600 shadow-sm hover:bg-gray-50 focus:shadow-none focus:outline-none dark:border-slate-600 dark:bg-slate-700 dark:text-slate-100 dark:hover:bg-slate-600 dark:hover:text-white"
>
<span>下一页</span>
<span class="i-tabler-arrow-right text-lg transition-all group-hover:translate-x-1"></span>
</a>
</div>
</div>
</th:block>
</html>
9 changes: 6 additions & 3 deletions templates/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ <h2 class="inline-flex items-center gap-2 text-base dark:text-slate-50">
<th:block th:replace="~{modules/sidebar :: sidebar(prepend = ~{::sidebar_prepend})}"></th:block>
</th:block>
<th:block th:fragment="content">
<div x-data="postUpvote" class="rounded-xl bg-white p-4 dark:bg-slate-800">
<div x-data="upvote('post','content.halo.run','posts')" class="rounded-xl bg-white p-4 dark:bg-slate-800">
<div th:attr="x-data=|{name:'${post.metadata.name}'}|" class="flex items-center justify-between">
<div class="inline-flex items-center justify-start gap-2">
<a th:href="@{${post.owner.permalink}}" th:title="${post.owner.displayName}">
Expand All @@ -53,8 +53,11 @@ <h2 class="inline-flex items-center gap-2 text-base dark:text-slate-50">
<span class="text-gray-300 dark:text-slate-200">/</span>
<span th:text="|${post.stats?.comment ?:0} 评论|"> </span>
<span class="text-gray-300 dark:text-slate-200">/</span>
<span th:attr="data-upvote-post-name=${post.metadata.name}" th:text="|${post.stats?.upvote ?:0} 点赞|">
</span>
<div>
<span th:attr="data-upvote-post-name=${post.metadata.name}" th:text="|${post.stats?.upvote ?:0}|">
</span>
<span> 点赞 </span>
</div>
</div>
</div>
</div>
Expand Down

0 comments on commit e3c2d95

Please sign in to comment.