mirror of https://github.com/usbharu/Hideout.git
feat: タイムラインを読めるように
This commit is contained in:
parent
88a61ba97f
commit
711084e366
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.usbharu.hideout.core.application.domainevent.subscribers
|
||||||
|
|
||||||
|
class RegisterLocalUserSetHomeTimelineSubscriber(private val domainEventSubscriber: DomainEventSubscriber) :
|
||||||
|
Subscriber {
|
||||||
|
init {
|
||||||
|
domainEventSubscriber.subscribe<>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//todo userdetailにdomain event付けて createのイベントで反応させる タイムラインを新しく一つ作って userdetailのhometimelineに紐づけて自分自身をtimleine relationshipに入れる
|
|
@ -2,17 +2,18 @@ package dev.usbharu.hideout.core.application.domainevent.subscribers
|
||||||
|
|
||||||
import dev.usbharu.hideout.core.domain.event.post.PostEvent
|
import dev.usbharu.hideout.core.domain.event.post.PostEvent
|
||||||
import dev.usbharu.hideout.core.domain.event.post.PostEventBody
|
import dev.usbharu.hideout.core.domain.event.post.PostEventBody
|
||||||
|
import dev.usbharu.hideout.core.external.timeline.TimelineStore
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import org.springframework.stereotype.Component
|
import org.springframework.stereotype.Component
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
class TimelinePostCreateSubscriber(domainEventSubscriber: DomainEventSubscriber) : Subscriber {
|
class TimelinePostCreateSubscriber(
|
||||||
|
private val timelineStore: TimelineStore,
|
||||||
|
domainEventSubscriber: DomainEventSubscriber
|
||||||
|
) : Subscriber {
|
||||||
init {
|
init {
|
||||||
domainEventSubscriber.subscribe<PostEventBody>(PostEvent.CREATE.eventName) {
|
domainEventSubscriber.subscribe<PostEventBody>(PostEvent.CREATE.eventName) {
|
||||||
val post = it.body.getPost()
|
timelineStore.addPost(it.body.getPost())
|
||||||
val actor = it.body.getActor()
|
|
||||||
|
|
||||||
logger.info("New Post! : {}", post)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package dev.usbharu.hideout.core.application.timeline
|
package dev.usbharu.hideout.core.application.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.core.application.post.PostDetail
|
||||||
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
|
import dev.usbharu.hideout.core.application.shared.AbstractApplicationService
|
||||||
import dev.usbharu.hideout.core.application.shared.Transaction
|
import dev.usbharu.hideout.core.application.shared.Transaction
|
||||||
import dev.usbharu.hideout.core.domain.model.post.PostId
|
import dev.usbharu.hideout.core.domain.model.post.PostId
|
||||||
import dev.usbharu.hideout.core.domain.model.support.page.PaginationList
|
import dev.usbharu.hideout.core.domain.model.support.page.PaginationList
|
||||||
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
|
import dev.usbharu.hideout.core.domain.model.support.principal.Principal
|
||||||
import dev.usbharu.hideout.core.domain.model.support.timelineobjectdetail.TimelineObjectDetail
|
|
||||||
import dev.usbharu.hideout.core.domain.model.timeline.TimelineId
|
import dev.usbharu.hideout.core.domain.model.timeline.TimelineId
|
||||||
import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository
|
import dev.usbharu.hideout.core.domain.model.timeline.TimelineRepository
|
||||||
import dev.usbharu.hideout.core.external.timeline.ReadTimelineOption
|
import dev.usbharu.hideout.core.external.timeline.ReadTimelineOption
|
||||||
|
@ -19,11 +19,11 @@ class ReadTimelineApplicationService(
|
||||||
private val timelineRepository: TimelineRepository,
|
private val timelineRepository: TimelineRepository,
|
||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
) :
|
) :
|
||||||
AbstractApplicationService<ReadTimeline, PaginationList<TimelineObjectDetail, PostId>>(transaction, logger) {
|
AbstractApplicationService<ReadTimeline, PaginationList<PostDetail, PostId>>(transaction, logger) {
|
||||||
override suspend fun internalExecute(
|
override suspend fun internalExecute(
|
||||||
command: ReadTimeline,
|
command: ReadTimeline,
|
||||||
principal: Principal
|
principal: Principal
|
||||||
): PaginationList<TimelineObjectDetail, PostId> {
|
): PaginationList<PostDetail, PostId> {
|
||||||
val findById = timelineRepository.findById(TimelineId(command.timelineId))
|
val findById = timelineRepository.findById(TimelineId(command.timelineId))
|
||||||
?: throw IllegalArgumentException("Timeline ${command.timelineId} not found.")
|
?: throw IllegalArgumentException("Timeline ${command.timelineId} not found.")
|
||||||
|
|
||||||
|
@ -33,12 +33,48 @@ class ReadTimelineApplicationService(
|
||||||
command.remoteOnly
|
command.remoteOnly
|
||||||
)
|
)
|
||||||
|
|
||||||
return timelineStore.readTimeline(
|
val timeline = timelineStore.readTimeline(
|
||||||
findById,
|
findById,
|
||||||
readTimelineOption,
|
readTimelineOption,
|
||||||
command.page,
|
command.page,
|
||||||
principal,
|
principal,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val postDetailList = timeline.map {
|
||||||
|
|
||||||
|
val reply = if (it.replyPost != null) {
|
||||||
|
PostDetail.of(
|
||||||
|
it.replyPost,
|
||||||
|
it.replyPostActor!!,
|
||||||
|
it.replyPostActorIconMedia,
|
||||||
|
it.replyPostMedias.orEmpty()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
val repost = if (it.repostPost != null) {
|
||||||
|
PostDetail.of(
|
||||||
|
it.repostPost,
|
||||||
|
it.repostPostActor!!,
|
||||||
|
it.repostPostActorIconMedia,
|
||||||
|
it.repostPostMedias.orEmpty()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
PostDetail.of(
|
||||||
|
it.post,
|
||||||
|
it.postActor,
|
||||||
|
it.postActorIconMedia,
|
||||||
|
it.postMedias,
|
||||||
|
reply,
|
||||||
|
repost
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return PaginationList(postDetailList, timeline.next, timeline.prev)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -52,7 +52,7 @@ import org.springframework.security.web.SecurityFilterChain
|
||||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
|
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity(debug = true)
|
@EnableWebSecurity(debug = false)
|
||||||
class SecurityConfig {
|
class SecurityConfig {
|
||||||
@Bean
|
@Bean
|
||||||
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
|
fun passwordEncoder(): PasswordEncoder = BCryptPasswordEncoder()
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package dev.usbharu.hideout.core.interfaces.web.timeline
|
||||||
|
|
||||||
|
import dev.usbharu.hideout.core.application.exception.InternalServerException
|
||||||
|
import dev.usbharu.hideout.core.application.shared.Transaction
|
||||||
|
import dev.usbharu.hideout.core.application.timeline.ReadTimeline
|
||||||
|
import dev.usbharu.hideout.core.application.timeline.ReadTimelineApplicationService
|
||||||
|
import dev.usbharu.hideout.core.domain.model.support.page.Page
|
||||||
|
import dev.usbharu.hideout.core.domain.model.userdetails.UserDetailRepository
|
||||||
|
import dev.usbharu.hideout.core.infrastructure.springframework.SpringSecurityFormLoginPrincipalContextHolder
|
||||||
|
import org.springframework.stereotype.Controller
|
||||||
|
import org.springframework.ui.Model
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
class TimelineController(
|
||||||
|
private val readTimelineApplicationService: ReadTimelineApplicationService,
|
||||||
|
private val userDetailRepository: UserDetailRepository,
|
||||||
|
private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder,
|
||||||
|
private val transaction: Transaction
|
||||||
|
) {
|
||||||
|
@GetMapping("/home")
|
||||||
|
suspend fun homeTimeline(model: Model, @RequestParam sinceId: String?, @RequestParam maxId: String?): String {
|
||||||
|
val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal()
|
||||||
|
val userDetail = transaction.transaction {
|
||||||
|
userDetailRepository.findByActorId(principal.actorId.id)
|
||||||
|
?: throw InternalServerException("UserDetail not found.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val homeTimelineId = userDetail.homeTimelineId!!
|
||||||
|
val execute = readTimelineApplicationService.execute(
|
||||||
|
ReadTimeline(
|
||||||
|
timelineId = homeTimelineId.value,
|
||||||
|
mediaOnly = false,
|
||||||
|
localOnly = false,
|
||||||
|
remoteOnly = false,
|
||||||
|
page = Page.of(
|
||||||
|
maxId = maxId?.toLongOrNull(),
|
||||||
|
sinceId = sinceId?.toLongOrNull()
|
||||||
|
)
|
||||||
|
), principal
|
||||||
|
)
|
||||||
|
|
||||||
|
model.addAttribute("timeline", execute)
|
||||||
|
|
||||||
|
return "homeTimeline"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<th:block th:fragment="simple-timline(timelineObject,href)">
|
||||||
|
<!--/*@thymesVar id="timelineObject" type="dev.usbharu.hideout.core.domain.model.support.page.PaginationList<dev.usbharu.hideout.core.application.post.PostDetail,dev.usbharu.hideout.core.domain.model.post.PostId>"*/-->
|
||||||
|
<div th:if="${timelineObject.prev == null}">
|
||||||
|
<a th:href="${href + '/?maxId=' + timelineObject.prev}"></a>
|
||||||
|
</div>
|
||||||
|
<div th:each="postDetail : ${timelineObject}">
|
||||||
|
<th:block th:replace="fragments-post :: single-simple-post(${postDetail})"></th:block>
|
||||||
|
</div>
|
||||||
|
<div th:if="${timelineObject.next == null}">
|
||||||
|
<a th:href="${href + '/?sinceId=' + timelineObject.next}"></a>
|
||||||
|
</div>
|
||||||
|
</th:block>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Title</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<div th:replace="fragments-timeline :: simple-timline(${timeline},'/home')"></div>
|
||||||
|
</noscript>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue