From 533582534f508bdbc76bc37e5e8524cb37f8497d Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 26 Aug 2024 17:47:41 +0900 Subject: [PATCH 01/19] =?UTF-8?q?feat:=20messages=E3=82=92=E3=83=9B?= =?UTF-8?q?=E3=83=83=E3=83=88=E3=83=AA=E3=83=AD=E3=83=BC=E3=83=89=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/config/MessageSourceConfig.kt | 28 +++++++++++++++++++ .../src/main/resources/application-dev.yml | 3 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/MessageSourceConfig.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/MessageSourceConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/MessageSourceConfig.kt new file mode 100644 index 00000000..846d89ca --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/MessageSourceConfig.kt @@ -0,0 +1,28 @@ +package dev.usbharu.hideout.core.config + +import org.springframework.boot.autoconfigure.context.MessageSourceProperties +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.context.MessageSource +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Profile +import org.springframework.context.support.ReloadableResourceBundleMessageSource + +@Configuration +@Profile("dev") +class MessageSourceConfig { + @Bean + fun messageSource(messageSourceProperties: MessageSourceProperties): MessageSource { + val reloadableResourceBundleMessageSource = ReloadableResourceBundleMessageSource() + reloadableResourceBundleMessageSource.setBasename("classpath:" + messageSourceProperties.basename) + reloadableResourceBundleMessageSource.setCacheSeconds(0) + return reloadableResourceBundleMessageSource + } + + @Bean + @Profile("dev") + @ConfigurationProperties(prefix = "spring.messages") + fun messageSourceProperties(): MessageSourceProperties { + return MessageSourceProperties() + } +} \ No newline at end of file diff --git a/hideout-core/src/main/resources/application-dev.yml b/hideout-core/src/main/resources/application-dev.yml index a6d4118b..2c19a35e 100644 --- a/hideout-core/src/main/resources/application-dev.yml +++ b/hideout-core/src/main/resources/application-dev.yml @@ -29,7 +29,8 @@ spring: virtual: enabled: true messages: - basename: messages.hideout-web-messages + basename: messages/hideout-web-messages + cache-duration: -1 thymeleaf: cache: false server: From c48694ab0b73867cecfa561de628406274ff192a Mon Sep 17 00:00:00 2001 From: usbharu Date: Mon, 26 Aug 2024 17:50:03 +0900 Subject: [PATCH 02/19] =?UTF-8?q?feat:=20/auth/sign=5Fup=20=E3=82=92?= =?UTF-8?q?=E6=94=B9=E8=89=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../instance/GetLocalInstanceApplicationService.kt | 8 ++++---- .../interfaces/{api => web}/auth/AuthController.kt | 10 ++++++++-- .../interfaces/{api => web}/auth/SignUpForm.kt | 2 +- .../messages/hideout-web-messages.properties | 3 +++ .../messages/hideout-web-messages_en_US.properties | 3 +++ .../messages/hideout-web-messages_ja_JP.properties | 3 +++ .../src/main/resources/templates/sign_up.html | 14 +++++++++++--- 7 files changed, 33 insertions(+), 10 deletions(-) rename hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/{api => web}/auth/AuthController.kt (80%) rename hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/{api => web}/auth/SignUpForm.kt (68%) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt index b96b7e06..557737ed 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/instance/GetLocalInstanceApplicationService.kt @@ -19,7 +19,7 @@ class GetLocalInstanceApplicationService( transaction, logger ) { - var cachedInstance: Instance? = null + private var cachedInstance: Instance? = null override suspend fun internalExecute(command: Unit, principal: Principal): Instance { if (cachedInstance != null) { @@ -28,9 +28,9 @@ class GetLocalInstanceApplicationService( } val instance = ( - instanceRepository.findByUrl(applicationConfig.url.toURI()) - ?: throw InternalServerException("Local instance not found.") - ) + instanceRepository.findByUrl(applicationConfig.url.toURI()) + ?: throw InternalServerException("Local instance not found.") + ) cachedInstance = Instance.of(instance) @Suppress("UnsafeCallOnNullableType") diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/AuthController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/AuthController.kt similarity index 80% rename from hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/AuthController.kt rename to hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/AuthController.kt index b19f3c4a..9b0d297b 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/AuthController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/AuthController.kt @@ -14,13 +14,15 @@ * limitations under the License. */ -package dev.usbharu.hideout.core.interfaces.api.auth +package dev.usbharu.hideout.core.interfaces.web.auth import dev.usbharu.hideout.core.application.actor.RegisterLocalActor import dev.usbharu.hideout.core.application.actor.RegisterLocalActorApplicationService +import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous import jakarta.servlet.http.HttpServletRequest import org.springframework.stereotype.Controller +import org.springframework.ui.Model import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.ModelAttribute @@ -29,10 +31,14 @@ import org.springframework.web.bind.annotation.PostMapping @Controller class AuthController( private val registerLocalActorApplicationService: RegisterLocalActorApplicationService, + private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, ) { @GetMapping("/auth/sign_up") @Suppress("FunctionOnlyReturningConstant") - fun signUp(): String = "sign_up" + suspend fun signUp(model: Model): String { + model.addAttribute("instance", getLocalInstanceApplicationService.execute(Unit, Anonymous)) + return "sign_up" + } @PostMapping("/auth/sign_up") suspend fun signUp(@Validated @ModelAttribute signUpForm: SignUpForm, request: HttpServletRequest): String { diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/SignUpForm.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/SignUpForm.kt similarity index 68% rename from hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/SignUpForm.kt rename to hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/SignUpForm.kt index d70eb9c2..320187d8 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/api/auth/SignUpForm.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/auth/SignUpForm.kt @@ -1,4 +1,4 @@ -package dev.usbharu.hideout.core.interfaces.api.auth +package dev.usbharu.hideout.core.interfaces.web.auth data class SignUpForm( val username: String, diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index c22c2992..6a47f1b5 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -1,3 +1,6 @@ +auth-signUp.password=\u30D1\u30B9\u30EF\u30FC\u30C9 +auth-signUp.register=\u767B\u9332\u3059\u308B +auth-signUp.username=\u30E6\u30FC\u30B6\u30FC\u540D common.audio=\u30AA\u30FC\u30C7\u30A3\u30AA common.audio-download-link=\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 common.empty=\u8868\u793A\u3059\u308B\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093 diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties index f32efecd..f85b5d8a 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties @@ -1,3 +1,6 @@ +auth-signUp.password=Password +auth-signUp.register=Register Account +auth-signUp.username=Username common.audio=Audio common.audio-download-link=Download the audio. common.empty=Empty diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index c22c2992..6a47f1b5 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -1,3 +1,6 @@ +auth-signUp.password=\u30D1\u30B9\u30EF\u30FC\u30C9 +auth-signUp.register=\u767B\u9332\u3059\u308B +auth-signUp.username=\u30E6\u30FC\u30B6\u30FC\u540D common.audio=\u30AA\u30FC\u30C7\u30A3\u30AA common.audio-download-link=\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u30C0\u30A6\u30F3\u30ED\u30FC\u30C9 common.empty=\u8868\u793A\u3059\u308B\u3082\u306E\u304C\u3042\u308A\u307E\u305B\u3093 diff --git a/hideout-core/src/main/resources/templates/sign_up.html b/hideout-core/src/main/resources/templates/sign_up.html index 63f57c5a..52d7abdd 100644 --- a/hideout-core/src/main/resources/templates/sign_up.html +++ b/hideout-core/src/main/resources/templates/sign_up.html @@ -2,13 +2,21 @@ - SignUp + Register Account + +
- - +
+ + +
+
+ + +
From 992cc18c6226b9b1d3d8a1d777aaedd5e03f5a05 Mon Sep 17 00:00:00 2001 From: usbharu Date: Tue, 27 Aug 2024 10:43:08 +0900 Subject: [PATCH 03/19] =?UTF-8?q?feat:=20/users/:id=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/application/actor/ActorDetail.kt | 38 ++++++++++++++ .../core/application/actor/GetActorDetail.kt | 8 +++ .../actor/GetActorDetailApplicationService.kt | 49 +++++++++++++++++++ .../hideout/core/config/SecurityConfig.kt | 1 + .../core/domain/model/support/acct/Acct.kt | 10 ++++ .../interfaces/web/user/UserController.kt | 31 ++++++++++++ .../messages/hideout-web-messages.properties | 3 +- .../hideout-web-messages_ja_JP.properties | 3 +- .../main/resources/templates/userById.html | 14 ++++++ 9 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt create mode 100644 hideout-core/src/main/resources/templates/userById.html diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt new file mode 100644 index 00000000..3398d719 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt @@ -0,0 +1,38 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.domain.model.actor.Actor +import java.net.URI + +data class ActorDetail( + val id: Long, + val name: String, + val screenName: String, + val host: String, + val remoteUrl: String?, + val locked: Boolean, + val description: String, + val postsCount: Int, + val iconUrl: URI?, + val bannerURL: URI?, + val followingCount: Int?, + val followersCount: Int? +) { + companion object { + fun of(actor: Actor, iconUrl: URI?, bannerURL: URI?): ActorDetail { + return ActorDetail( + id = actor.id.id, + name = actor.name.name, + screenName = actor.screenName.screenName, + host = actor.url.host, + remoteUrl = actor.url.toString(), + locked = actor.locked, + description = actor.description.description, + postsCount = actor.postsCount.postsCount, + iconUrl = iconUrl, + bannerURL = bannerURL, + followingCount = actor.followingCount?.relationshipCount, + followersCount = actor.followersCount?.relationshipCount + ) + } + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt new file mode 100644 index 00000000..8089a404 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetail.kt @@ -0,0 +1,8 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.domain.model.support.acct.Acct + +data class GetActorDetail( + val actorName: Acct? = null, + val id: Long? = null +) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt new file mode 100644 index 00000000..f417fe5d --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/GetActorDetailApplicationService.kt @@ -0,0 +1,49 @@ +package dev.usbharu.hideout.core.application.actor + +import dev.usbharu.hideout.core.application.shared.AbstractApplicationService +import dev.usbharu.hideout.core.application.shared.Transaction +import dev.usbharu.hideout.core.config.ApplicationConfig +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.actor.ActorRepository +import dev.usbharu.hideout.core.domain.model.media.MediaRepository +import dev.usbharu.hideout.core.domain.model.support.principal.Principal +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Component + +@Component +class GetActorDetailApplicationService( + private val actorRepository: ActorRepository, + private val mediaRepository: MediaRepository, + private val applicationConfig: ApplicationConfig, + transaction: Transaction +) : + AbstractApplicationService( + transaction, logger + ) { + override suspend fun internalExecute(command: GetActorDetail, principal: Principal): ActorDetail { + val actor = if (command.id != null) { + actorRepository.findById(ActorId(command.id)) + ?: throw IllegalArgumentException("Actor ${command.id} not found.") + } else if (command.actorName != null) { + + val host = if (command.actorName.host.isEmpty()) { + applicationConfig.url.host + } else { + command.actorName.host + } + actorRepository.findByNameAndDomain(command.actorName.userpart, host) + ?: throw IllegalArgumentException("Actor ${command.actorName} not found.") + } else { + throw IllegalArgumentException("id and actorName are null.") + } + + val iconUrl = actor.icon?.let { mediaRepository.findById(it)?.url } + val bannerUrl = actor.banner?.let { mediaRepository.findById(it)?.url } + + return ActorDetail.of(actor, iconUrl, bannerUrl) + } + + companion object { + private val logger = LoggerFactory.getLogger(GetActorDetailApplicationService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt index 2eccad56..2c8217d3 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/config/SecurityConfig.kt @@ -87,6 +87,7 @@ class SecurityConfig { authorize(GET, "/auth/sign_up", hasRole("ANONYMOUS")) authorize(POST, "/auth/sign_up", permitAll) authorize(GET, "/users/{username}/posts/{postId}", permitAll) + authorize(GET, "/users/{userid}", permitAll) authorize(GET, "/files/*", permitAll) authorize(POST, "/publish", authenticated) authorize(GET, "/publish", authenticated) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt index 8be92e3a..148e01ca 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/domain/model/support/acct/Acct.kt @@ -5,4 +5,14 @@ data class Acct( val host: String ) { override fun toString(): String = "acct:$userpart@$host" + + companion object { + + fun of(acct: String): Acct { + return Acct( + acct.substringBeforeLast('@'), + acct.substringAfterLast('@', "") + ) + } + } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt new file mode 100644 index 00000000..d07a79ea --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt @@ -0,0 +1,31 @@ +package dev.usbharu.hideout.core.interfaces.web.user + +import dev.usbharu.hideout.core.application.actor.GetActorDetail +import dev.usbharu.hideout.core.application.actor.GetActorDetailApplicationService +import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService +import dev.usbharu.hideout.core.domain.model.support.acct.Acct +import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous +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.PathVariable + +@Controller +class UserController( + private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, + private val getUserDetailApplicationService: GetActorDetailApplicationService, + private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder, +) { + @GetMapping("/users/{name}") + suspend fun userById(@PathVariable name: String, model: Model): String { + val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() + + model.addAttribute("instance", getLocalInstanceApplicationService.execute(Unit, Anonymous)) + model.addAttribute( + "user", + getUserDetailApplicationService.execute(GetActorDetail(Acct.of(name)), principal) + ) + return "userById" + } +} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index 6a47f1b5..6423f1c9 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -21,4 +21,5 @@ post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6 post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 -post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file +post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index 6a47f1b5..6423f1c9 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -21,4 +21,5 @@ post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6 post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 -post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 \ No newline at end of file +post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/templates/userById.html b/hideout-core/src/main/resources/templates/userById.html new file mode 100644 index 00000000..ded4a2a7 --- /dev/null +++ b/hideout-core/src/main/resources/templates/userById.html @@ -0,0 +1,14 @@ + + + + + User - hideout + + + + + \ No newline at end of file From 0463ad6b690b68ce1057988ffce7c58d8fe9068a Mon Sep 17 00:00:00 2001 From: usbharu Date: Thu, 29 Aug 2024 14:02:16 +0900 Subject: [PATCH 04/19] wip --- .../core/application/actor/ActorDetail.kt | 4 +- .../application/timeline/GetUserTimeline.kt | 5 + .../GetUserTimelineApplicationService.kt | 49 ++++++++ .../ExposedUserTimelineQueryService.kt | 110 ++++++++++++++++++ .../ExposedPostRepository.kt | 41 +++++-- .../exposedrepository/MediaRepositoryImpl.kt | 17 +++ .../interfaces/web/user/UserController.kt | 24 +++- .../usertimeline/UserTimelineQueryService.kt | 12 ++ .../messages/hideout-web-messages.properties | 3 + .../hideout-web-messages_en_US.properties | 5 +- .../hideout-web-messages_ja_JP.properties | 3 + .../main/resources/templates/userById.html | 25 +++- .../exposedquery/ExposedStatusQueryService.kt | 38 +----- 13 files changed, 283 insertions(+), 53 deletions(-) create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimeline.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimelineApplicationService.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ExposedUserTimelineQueryService.kt create mode 100644 hideout-core/src/main/kotlin/dev/usbharu/hideout/core/query/usertimeline/UserTimelineQueryService.kt diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt index 3398d719..5a5eff44 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/actor/ActorDetail.kt @@ -15,7 +15,7 @@ data class ActorDetail( val iconUrl: URI?, val bannerURL: URI?, val followingCount: Int?, - val followersCount: Int? + val followersCount: Int?, ) { companion object { fun of(actor: Actor, iconUrl: URI?, bannerURL: URI?): ActorDetail { @@ -31,7 +31,7 @@ data class ActorDetail( iconUrl = iconUrl, bannerURL = bannerURL, followingCount = actor.followingCount?.relationshipCount, - followersCount = actor.followersCount?.relationshipCount + followersCount = actor.followersCount?.relationshipCount, ) } } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimeline.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimeline.kt new file mode 100644 index 00000000..8ebc7d15 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimeline.kt @@ -0,0 +1,5 @@ +package dev.usbharu.hideout.core.application.timeline + +import dev.usbharu.hideout.core.domain.model.support.page.Page + +data class GetUserTimeline(val id: Long, val page: Page) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimelineApplicationService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimelineApplicationService.kt new file mode 100644 index 00000000..0019a2d8 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/application/timeline/GetUserTimelineApplicationService.kt @@ -0,0 +1,49 @@ +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.Transaction +import dev.usbharu.hideout.core.domain.model.actor.ActorId +import dev.usbharu.hideout.core.domain.model.post.PostId +import dev.usbharu.hideout.core.domain.model.post.PostRepository +import dev.usbharu.hideout.core.domain.model.post.Visibility +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.query.usertimeline.UserTimelineQueryService +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class GetUserTimelineApplicationService( + private val userTimelineQueryService: UserTimelineQueryService, + private val postRepository: PostRepository, + transaction: Transaction +) : + AbstractApplicationService>(transaction, logger) { + override suspend fun internalExecute( + command: GetUserTimeline, + principal: Principal + ): PaginationList { + val postList = postRepository.findByActorIdAndVisibilityInList( + ActorId(command.id), + listOf(Visibility.PUBLIC, Visibility.UNLISTED, Visibility.FOLLOWERS), + command.page + ) + + val postIdList = + postList.mapNotNull { it.repostId } + postList.mapNotNull { it.replyId } + postList.map { it.id } + + val postDetailMap = userTimelineQueryService.findByIdAll(postIdList, principal).associateBy { it.id } + + return PaginationList(postList.mapNotNull { + postDetailMap[it.id.id]?.copy( + repost = postDetailMap[it.repostId?.id], + reply = postDetailMap[it.replyId?.id] + ) + }, postList.next, postList.prev) + } + + companion object { + private val logger = LoggerFactory.getLogger(GetUserTimelineApplicationService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ExposedUserTimelineQueryService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ExposedUserTimelineQueryService.kt new file mode 100644 index 00000000..922abdca --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedquery/ExposedUserTimelineQueryService.kt @@ -0,0 +1,110 @@ +package dev.usbharu.hideout.core.infrastructure.exposedquery + +import dev.usbharu.hideout.core.application.post.ActorDetail +import dev.usbharu.hideout.core.application.post.MediaDetail +import dev.usbharu.hideout.core.application.post.PostDetail +import dev.usbharu.hideout.core.domain.model.post.PostId +import dev.usbharu.hideout.core.domain.model.post.Visibility +import dev.usbharu.hideout.core.domain.model.support.principal.Principal +import dev.usbharu.hideout.core.infrastructure.exposedrepository.* +import dev.usbharu.hideout.core.query.usertimeline.UserTimelineQueryService +import org.jetbrains.exposed.sql.* +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Repository +import java.net.URI + +@Repository +class ExposedUserTimelineQueryService : UserTimelineQueryService, AbstractRepository() { + + protected fun authorizedQuery(principal: Principal? = null): QueryAlias { + if (principal == null) { + return Posts + .selectAll() + .where { + Posts.visibility eq Visibility.PUBLIC.name or (Posts.visibility eq Visibility.UNLISTED.name) + }.alias("authorized_table") + } + + val relationshipsAlias = Relationships.alias("inverse_relationships") + + return Posts + .leftJoin(PostsVisibleActors) + .leftJoin(Relationships, onColumn = { Posts.actorId }, otherColumn = { actorId }) + .leftJoin( + relationshipsAlias, + onColumn = { Posts.actorId }, + otherColumn = { relationshipsAlias[Relationships.targetActorId] } + ) + .select(Posts.columns) + .where { + Posts.visibility eq Visibility.PUBLIC.name or + (Posts.visibility eq Visibility.UNLISTED.name) or + (Posts.visibility eq Visibility.DIRECT.name and (PostsVisibleActors.actorId eq principal.actorId.id)) or + (Posts.visibility eq Visibility.FOLLOWERS.name and (Relationships.blocking eq false and (relationshipsAlias[Relationships.following] eq true))) or + (Posts.actorId eq principal.actorId.id) + } + .alias("authorized_table") + } + + override suspend fun findByIdAll(idList: List, principal: Principal): List { + val authorizedQuery = authorizedQuery(principal) + + val iconMedia = Media.alias("ICON_MEDIA") + + return authorizedQuery + .leftJoin(PostsVisibleActors, { authorizedQuery[Posts.id] }, { PostsVisibleActors.postId }) + .leftJoin(Actors, { authorizedQuery[Posts.actorId] }, { Actors.id }) + .leftJoin(iconMedia, { Actors.icon }, { iconMedia[Media.id] }) + .leftJoin(PostsMedia, { authorizedQuery[Posts.id] }, { PostsMedia.postId }) + .leftJoin(Media, { PostsMedia.mediaId }, { Media.id }) + .selectAll() + .where { authorizedQuery[Posts.id] inList idList.map { it.id } } + .groupBy { it[authorizedQuery[Posts.id]] } + .map { it.value } + .map { + toPostDetail(it.first(), authorizedQuery, iconMedia).copy( + mediaDetailList = it.mapNotNull { resultRow -> + resultRow.toMediaOrNull()?.let { it1 -> MediaDetail.of(it1) } + } + ) + } + } + + private fun toPostDetail(it: ResultRow, authorizedQuery: QueryAlias, iconMedia: Alias): PostDetail { + return PostDetail( + it[authorizedQuery[Posts.id]], + ActorDetail( + actorId = it[authorizedQuery[Posts.actorId]], + instanceId = it[Actors.instance], + name = it[Actors.name], + domain = it[Actors.domain], + screenName = it[Actors.screenName], + url = URI.create(it[Actors.url]), + locked = it[Actors.locked], + icon = it.getOrNull(iconMedia[Media.url])?.let { URI.create(it) } + ), + overview = it[authorizedQuery[Posts.overview]], + text = it[authorizedQuery[Posts.text]], + content = it[authorizedQuery[Posts.content]], + createdAt = it[authorizedQuery[Posts.createdAt]], + visibility = Visibility.valueOf(it[authorizedQuery[Posts.visibility]]), + pureRepost = false, + url = URI.create(it[authorizedQuery[Posts.url]]), + apId = URI.create(it[authorizedQuery[Posts.apId]]), + repost = null, + reply = null, + sensitive = it[authorizedQuery[Posts.sensitive]], + deleted = it[authorizedQuery[Posts.deleted]], + mediaDetailList = emptyList(), + moveTo = null + ) + } + + override val logger: Logger + get() = Companion.logger + + companion object { + private val logger = LoggerFactory.getLogger(ExposedUserTimelineQueryService::class.java) + } +} \ No newline at end of file diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedPostRepository.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedPostRepository.kt index 8dc2184a..9408d01a 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedPostRepository.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/ExposedPostRepository.kt @@ -211,17 +211,38 @@ class ExposedPostRepository( visibilityList: List, of: Page? ): PaginationList { + val postList = query { + val query = Posts + .selectAll() + .where { + Posts.actorId eq actorId.id and (visibility inList visibilityList.map { it.name }) + } + + if (of?.minId != null) { + query.orderBy(Posts.createdAt, SortOrder.ASC) + of.minId?.let { query.andWhere { Posts.id greater it } } + of.maxId?.let { query.andWhere { Posts.id less it } } + } else { + query.orderBy(Posts.createdAt, SortOrder.DESC) + of?.sinceId?.let { query.andWhere { Posts.id greater it } } + of?.maxId?.let { query.andWhere { Posts.id less it } } + } + + of?.limit?.let { query.limit(it) } + + query.let(postQueryMapper::map) + } + + val posts = if (of?.minId != null) { + postList.reversed() + } else { + postList + } + return PaginationList( - query { - Posts - .selectAll() - .where { - Posts.actorId eq actorId.id and (visibility inList visibilityList.map { it.name }) - } - .let(postQueryMapper::map) - }, - null, - null + posts, + posts.lastOrNull()?.id, + posts.firstOrNull()?.id ) } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt index d5bd5f2a..0f145fbe 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/infrastructure/exposedrepository/MediaRepositoryImpl.kt @@ -108,6 +108,23 @@ fun ResultRow.toMedia(): EntityMedia { ) } +fun ResultRow.toMediaOrNull(): EntityMedia? { + val fileType = FileType.valueOf(this.getOrNull(Media.type) ?: return null) + val mimeType = this.getOrNull(Media.mimeType) ?: return null + return EntityMedia( + id = MediaId(this.getOrNull(Media.id) ?: return null), + name = MediaName(this.getOrNull(Media.name) ?: return null), + url = URI.create(this.getOrNull(Media.url) ?: return null), + remoteUrl = this[Media.remoteUrl]?.let { URI.create(it) }, + thumbnailUrl = this[Media.thumbnailUrl]?.let { URI.create(it) }, + type = FileType.valueOf(this[Media.type]), + blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) }, + mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType), + description = this[Media.description]?.let { MediaDescription(it) }, + actorId = ActorId(this[Media.actorId]) + ) +} + object Media : Table("media") { val id = long("id") val name = varchar("name", 255) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt index d07a79ea..a9a8979e 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/user/UserController.kt @@ -3,28 +3,48 @@ package dev.usbharu.hideout.core.interfaces.web.user import dev.usbharu.hideout.core.application.actor.GetActorDetail import dev.usbharu.hideout.core.application.actor.GetActorDetailApplicationService import dev.usbharu.hideout.core.application.instance.GetLocalInstanceApplicationService +import dev.usbharu.hideout.core.application.timeline.GetUserTimeline +import dev.usbharu.hideout.core.application.timeline.GetUserTimelineApplicationService import dev.usbharu.hideout.core.domain.model.support.acct.Acct +import dev.usbharu.hideout.core.domain.model.support.page.Page import dev.usbharu.hideout.core.domain.model.support.principal.Anonymous 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.PathVariable +import org.springframework.web.bind.annotation.RequestParam @Controller class UserController( private val getLocalInstanceApplicationService: GetLocalInstanceApplicationService, private val getUserDetailApplicationService: GetActorDetailApplicationService, private val springSecurityFormLoginPrincipalContextHolder: SpringSecurityFormLoginPrincipalContextHolder, + private val getUserTimelineApplicationService: GetUserTimelineApplicationService ) { @GetMapping("/users/{name}") - suspend fun userById(@PathVariable name: String, model: Model): String { + suspend fun userById( + @PathVariable name: String, + @RequestParam minId: Long?, + @RequestParam maxId: Long?, + @RequestParam sinceId: Long?, + model: Model + ): String { val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() model.addAttribute("instance", getLocalInstanceApplicationService.execute(Unit, Anonymous)) + val actorDetail = getUserDetailApplicationService.execute(GetActorDetail(Acct.of(name)), principal) model.addAttribute( "user", - getUserDetailApplicationService.execute(GetActorDetail(Acct.of(name)), principal) + actorDetail + ) + model.addAttribute( + "userTimeline", getUserTimelineApplicationService.execute( + GetUserTimeline( + actorDetail.id, + Page.of(maxId, sinceId, minId, 20) + ), principal + ) ) return "userById" } diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/query/usertimeline/UserTimelineQueryService.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/query/usertimeline/UserTimelineQueryService.kt new file mode 100644 index 00000000..129cc190 --- /dev/null +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/query/usertimeline/UserTimelineQueryService.kt @@ -0,0 +1,12 @@ +package dev.usbharu.hideout.core.query.usertimeline + +import dev.usbharu.hideout.core.application.post.PostDetail +import dev.usbharu.hideout.core.domain.model.post.PostId +import dev.usbharu.hideout.core.domain.model.support.principal.Principal + +interface UserTimelineQueryService { + /** + * replyやrepost等はnullになります + */ + suspend fun findByIdAll(idList: List, principal: Principal): List +} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index 6423f1c9..2b25be8d 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -22,4 +22,7 @@ post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.followersCount={0} \u30D5\u30A9\u30ED\u30EF\u30FC +user-by-id.followingCount={0} \u30D5\u30A9\u30ED\u30FC\u4E2D +user-by-id.postsCount={0} \u6295\u7A3F user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties index f85b5d8a..e679799d 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties @@ -20,4 +20,7 @@ post-form.new-posts-cw-title=Add content warning post-form.new-posts-form-label=What's on your mind? post-form.new-posts-submit=Submit! post.repost=Repost -post.repost-by=Repost by {0} \ No newline at end of file +post.repost-by=Repost by {0} +user-by-id.followersCount={0} Followers +user-by-id.followingCount={0} Following +user-by-id.postsCount={0} Posts \ No newline at end of file diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index 6423f1c9..2b25be8d 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -22,4 +22,7 @@ post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 +user-by-id.followersCount={0} \u30D5\u30A9\u30ED\u30EF\u30FC +user-by-id.followingCount={0} \u30D5\u30A9\u30ED\u30FC\u4E2D +user-by-id.postsCount={0} \u6295\u7A3F user-by-id.title={0} \u3055\u3093 - {1} \ No newline at end of file diff --git a/hideout-core/src/main/resources/templates/userById.html b/hideout-core/src/main/resources/templates/userById.html index ded4a2a7..88fa9727 100644 --- a/hideout-core/src/main/resources/templates/userById.html +++ b/hideout-core/src/main/resources/templates/userById.html @@ -7,8 +7,31 @@ \ No newline at end of file diff --git a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/ExposedStatusQueryService.kt b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/ExposedStatusQueryService.kt index 452a5a5d..d80009f1 100644 --- a/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/ExposedStatusQueryService.kt +++ b/hideout-mastodon/src/main/kotlin/dev/usbharu/hideout/mastodon/infrastructure/exposedquery/ExposedStatusQueryService.kt @@ -16,9 +16,8 @@ package dev.usbharu.hideout.mastodon.infrastructure.exposedquery -import dev.usbharu.hideout.core.domain.model.actor.ActorId import dev.usbharu.hideout.core.domain.model.emoji.CustomEmoji -import dev.usbharu.hideout.core.domain.model.media.* +import dev.usbharu.hideout.core.domain.model.media.FileType import dev.usbharu.hideout.core.domain.model.post.Visibility import dev.usbharu.hideout.core.domain.model.support.principal.Principal import dev.usbharu.hideout.core.infrastructure.exposedrepository.* @@ -30,7 +29,6 @@ import dev.usbharu.hideout.mastodon.query.StatusQuery import dev.usbharu.hideout.mastodon.query.StatusQueryService import org.jetbrains.exposed.sql.* import org.springframework.stereotype.Repository -import java.net.URI import dev.usbharu.hideout.core.domain.model.media.Media as EntityMedia import dev.usbharu.hideout.mastodon.interfaces.api.generated.model.CustomEmoji as MastodonEmoji @@ -274,40 +272,6 @@ private fun toStatus(it: ResultRow, queryAlias: QueryAlias, inReplyToAlias: Alia editedAt = null ) -fun ResultRow.toMedia(): EntityMedia { - val fileType = FileType.valueOf(this[Media.type]) - val mimeType = this[Media.mimeType] - return EntityMedia( - id = MediaId(this[Media.id]), - name = MediaName(this[Media.name]), - url = URI.create(this[Media.url]), - remoteUrl = this[Media.remoteUrl]?.let { URI.create(it) }, - thumbnailUrl = this[Media.thumbnailUrl]?.let { URI.create(it) }, - type = fileType, - blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) }, - mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType), - description = this[Media.description]?.let { MediaDescription(it) }, - actorId = ActorId(this[Media.actorId]) - ) -} - -fun ResultRow.toMediaOrNull(): EntityMedia? { - val fileType = FileType.valueOf(this.getOrNull(Media.type) ?: return null) - val mimeType = this.getOrNull(Media.mimeType) ?: return null - return EntityMedia( - id = MediaId(this.getOrNull(Media.id) ?: return null), - name = MediaName(this.getOrNull(Media.name) ?: return null), - url = URI.create(this.getOrNull(Media.url) ?: return null), - remoteUrl = this[Media.remoteUrl]?.let { URI.create(it) }, - thumbnailUrl = this[Media.thumbnailUrl]?.let { URI.create(it) }, - type = FileType.valueOf(this[Media.type]), - blurHash = this[Media.blurhash]?.let { MediaBlurHash(it) }, - mimeType = MimeType(mimeType.substringBefore("/"), mimeType.substringAfter("/"), fileType), - description = this[Media.description]?.let { MediaDescription(it) }, - actorId = ActorId(this[Media.actorId]) - ) -} - fun EntityMedia.toMediaAttachments(): MediaAttachment = MediaAttachment( id = id.id.toString(), type = when (type) { From 57afdcdd7be79a966a3eb9f335d135d2b42c151d Mon Sep 17 00:00:00 2001 From: usbharu Date: Wed, 4 Sep 2024 15:48:48 +0900 Subject: [PATCH 05/19] wip --- .../interfaces/web/posts/PublishController.kt | 9 +++++---- .../core/interfaces/web/posts/PublishPost.kt | 8 +++++++- .../messages/hideout-web-messages.properties | 2 ++ .../hideout-web-messages_en_US.properties | 2 ++ .../hideout-web-messages_ja_JP.properties | 2 ++ .../main/resources/templates/post-postForm.html | 17 ++++++++++++++--- .../src/main/resources/templates/userById.html | 4 ++-- 7 files changed, 34 insertions(+), 10 deletions(-) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt index 86eb8db7..5620adf6 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishController.kt @@ -13,6 +13,7 @@ import org.springframework.ui.Model import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.ModelAttribute import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestParam @Controller class PublishController( @@ -22,7 +23,7 @@ class PublishController( private val userRegisterLocalPostApplicationService: RegisterLocalPostApplicationService ) { @GetMapping("/publish") - suspend fun publish(model: Model): String { + suspend fun publish(model: Model,@RequestParam replyTo: Long?,@RequestParam repost: Long?): String { val principal = springSecurityFormLoginPrincipalContextHolder.getPrincipal() if (principal.userDetailId == null) { @@ -35,7 +36,7 @@ class PublishController( val userDetail = getUserDetailApplicationService.execute(GetUserDetail(principal.userDetailId!!.id), principal) model.addAttribute("instance", instance) model.addAttribute("user", userDetail) - model.addAttribute("form", PublishPost()) + model.addAttribute("form", PublishPost(replyTo = replyTo, repost = repost)) return "post-postForm" } @@ -50,8 +51,8 @@ class PublishController( content = publishPost.status.orEmpty(), overview = publishPost.overview, visibility = Visibility.valueOf(publishPost.visibility.uppercase()), - repostId = null, - replyId = null, + repostId = publishPost.repost, + replyId = publishPost.replyTo, sensitive = false, mediaIds = emptyList() ) diff --git a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt index c732d2eb..be5bcb38 100644 --- a/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt +++ b/hideout-core/src/main/kotlin/dev/usbharu/hideout/core/interfaces/web/posts/PublishPost.kt @@ -1,3 +1,9 @@ package dev.usbharu.hideout.core.interfaces.web.posts -data class PublishPost(var status: String? = null, var overview: String? = null, var visibility: String = "PUBLIC") +data class PublishPost( + var status: String? = null, + var overview: String? = null, + var visibility: String = "PUBLIC", + var replyTo: Long? = null, + var repost: Long? = null +) diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages.properties b/hideout-core/src/main/resources/messages/hideout-web-messages.properties index 2b25be8d..f2b9318e 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages.properties @@ -19,7 +19,9 @@ post-form.new-posts=\u65B0\u3057\u3044\u6295\u7A3F! post-form.new-posts-cw=CW post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6CE8\u610F\u3092\u3064\u3051\u308B post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? +post-form.new-posts-replyTo=\u8FD4\u4FE1\u5148 post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B +post-form.new-posts.repost=\u30EA\u30DD\u30B9\u30C8 post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 user-by-id.followersCount={0} \u30D5\u30A9\u30ED\u30EF\u30FC diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties index e679799d..67b651f8 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_en_US.properties @@ -18,7 +18,9 @@ post-form.new-posts=New Posts! post-form.new-posts-cw=CW post-form.new-posts-cw-title=Add content warning post-form.new-posts-form-label=What's on your mind? +post-form.new-posts-replyTo=Reply to post-form.new-posts-submit=Submit! +post-form.new-posts.repost=Repost post.repost=Repost post.repost-by=Repost by {0} user-by-id.followersCount={0} Followers diff --git a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties index 2b25be8d..f2b9318e 100644 --- a/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties +++ b/hideout-core/src/main/resources/messages/hideout-web-messages_ja_JP.properties @@ -19,7 +19,9 @@ post-form.new-posts=\u65B0\u3057\u3044\u6295\u7A3F! post-form.new-posts-cw=CW post-form.new-posts-cw-title=\u30B3\u30F3\u30C6\u30F3\u30C4\u306B\u95B2\u89A7\u6CE8\u610F\u3092\u3064\u3051\u308B post-form.new-posts-form-label=\u4ECA\u306A\u306B\u3057\u3066\u308B? +post-form.new-posts-replyTo=\u8FD4\u4FE1\u5148 post-form.new-posts-submit=\u6295\u7A3F\u3059\u308B +post-form.new-posts.repost=\u30EA\u30DD\u30B9\u30C8 post.repost=\u30EA\u30DD\u30B9\u30C8 post.repost-by={0}\u304C\u30EA\u30DD\u30B9\u30C8 user-by-id.followersCount={0} \u30D5\u30A9\u30ED\u30EF\u30FC diff --git a/hideout-core/src/main/resources/templates/post-postForm.html b/hideout-core/src/main/resources/templates/post-postForm.html index a53bfba4..66ae1fd0 100644 --- a/hideout-core/src/main/resources/templates/post-postForm.html +++ b/hideout-core/src/main/resources/templates/post-postForm.html @@ -16,6 +16,14 @@
+
+ + +
+
+ + +
diff --git a/hideout-core/src/main/resources/templates/userById.html b/hideout-core/src/main/resources/templates/userById.html index 88fa9727..66212568 100644 --- a/hideout-core/src/main/resources/templates/userById.html +++ b/hideout-core/src/main/resources/templates/userById.html @@ -7,8 +7,8 @@