diff --git a/CHANGELOG.md b/CHANGELOG.md index cf8c4d2dfc..b601e3eeab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### New features 🚀 +* Setting random emoji icon when creating a new page (#603) + ### Design & UX 🔳 * Redesigned block toolbar (#590) diff --git a/app/src/main/java/com/agileburo/anytype/di/feature/DashboardDi.kt b/app/src/main/java/com/agileburo/anytype/di/feature/DashboardDi.kt index 8e793fd0ec..223faa48c9 100644 --- a/app/src/main/java/com/agileburo/anytype/di/feature/DashboardDi.kt +++ b/app/src/main/java/com/agileburo/anytype/di/feature/DashboardDi.kt @@ -11,6 +11,7 @@ import com.agileburo.anytype.domain.dashboard.interactor.CloseDashboard import com.agileburo.anytype.domain.dashboard.interactor.OpenDashboard import com.agileburo.anytype.domain.event.interactor.EventChannel import com.agileburo.anytype.domain.event.interactor.InterceptEvents +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider import com.agileburo.anytype.domain.misc.UrlBuilder import com.agileburo.anytype.domain.page.CreatePage import com.agileburo.anytype.presentation.desktop.HomeDashboardEventConverter @@ -93,9 +94,11 @@ class HomeDashboardModule { @Provides @PerScreen fun provideCreatePageUseCase( - repo: BlockRepository + repo: BlockRepository, + documentEmojiIconProvider: DocumentEmojiIconProvider ): CreatePage = CreatePage( - repo = repo + repo = repo, + documentEmojiIconProvider = documentEmojiIconProvider ) @Provides diff --git a/app/src/main/java/com/agileburo/anytype/di/feature/PageDI.kt b/app/src/main/java/com/agileburo/anytype/di/feature/PageDI.kt index 296ef7806d..d52ef8e719 100644 --- a/app/src/main/java/com/agileburo/anytype/di/feature/PageDI.kt +++ b/app/src/main/java/com/agileburo/anytype/di/feature/PageDI.kt @@ -12,6 +12,7 @@ import com.agileburo.anytype.domain.download.DownloadFile import com.agileburo.anytype.domain.download.Downloader import com.agileburo.anytype.domain.event.interactor.EventChannel import com.agileburo.anytype.domain.event.interactor.InterceptEvents +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider import com.agileburo.anytype.domain.misc.UrlBuilder import com.agileburo.anytype.domain.page.* import com.agileburo.anytype.domain.page.bookmark.SetupBookmark @@ -199,9 +200,11 @@ class PageModule { @Provides @PerScreen fun provideCreatePageUseCase( - repo: BlockRepository + repo: BlockRepository, + documentEmojiIconProvider: DocumentEmojiIconProvider ): CreatePage = CreatePage( - repo = repo + repo = repo, + documentEmojiIconProvider = documentEmojiIconProvider ) @Provides @@ -257,9 +260,11 @@ class PageModule { @Provides @PerScreen fun provideCreateDocumentUseCase( - repo: BlockRepository + repo: BlockRepository, + documentEmojiIconProvider: DocumentEmojiIconProvider ): CreateDocument = CreateDocument( - repo = repo + repo = repo, + documentEmojiProvider = documentEmojiIconProvider ) @Provides diff --git a/app/src/main/java/com/agileburo/anytype/di/main/EmojiModule.kt b/app/src/main/java/com/agileburo/anytype/di/main/EmojiModule.kt index c38486127a..b2d1954581 100644 --- a/app/src/main/java/com/agileburo/anytype/di/main/EmojiModule.kt +++ b/app/src/main/java/com/agileburo/anytype/di/main/EmojiModule.kt @@ -2,6 +2,8 @@ package com.agileburo.anytype.di.main import android.content.Context +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider +import com.agileburo.anytype.emojifier.data.DefaultDocumentEmojiIconProvider import com.agileburo.anytype.emojifier.suggest.EmojiSuggester import com.agileburo.anytype.emojifier.suggest.data.DefaultEmojiSuggestStorage import com.agileburo.anytype.emojifier.suggest.data.DefaultEmojiSuggester @@ -38,4 +40,10 @@ class EmojiModule { fun provideEmojiSuggestStorage(context: Context): EmojiSuggestStorage { return DefaultEmojiSuggestStorage(context, Gson()) } + + @Provides + @Singleton + fun provideDocumentEmojiIconProvider(): DocumentEmojiIconProvider { + return DefaultDocumentEmojiIconProvider() + } } \ No newline at end of file diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/mapper/MapperExtension.kt b/data/src/main/java/com/agileburo/anytype/data/auth/mapper/MapperExtension.kt index 9a3b100ef1..9debbe9652 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/mapper/MapperExtension.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/mapper/MapperExtension.kt @@ -396,7 +396,8 @@ fun Command.CreateDocument.toEntity() = CommandEntity.CreateDocument( context = context, target = target, prototype = prototype.toEntity(), - position = position.toEntity() + position = position.toEntity(), + emoji = emoji ) fun Command.Replace.toEntity() = CommandEntity.Replace( diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/model/CommandEntity.kt b/data/src/main/java/com/agileburo/anytype/data/auth/model/CommandEntity.kt index b3d50c4920..11b8e0c48e 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/model/CommandEntity.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/model/CommandEntity.kt @@ -75,7 +75,8 @@ class CommandEntity { val context: String, val target: String, val position: PositionEntity, - val prototype: BlockEntity.Prototype.Page + val prototype: BlockEntity.Prototype.Page, + val emoji: String? ) class Move( diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataRepository.kt b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataRepository.kt index e77c153c41..963fd5319c 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataRepository.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataRepository.kt @@ -34,7 +34,8 @@ class BlockDataRepository( command: Command.UpdateAlignment ) : Payload = factory.remote.updateAlignment(command.toEntity()).toDomain() - override suspend fun createPage(parentId: String) = factory.remote.createPage(parentId) + override suspend fun createPage(parentId: String, emoji: String?) = + factory.remote.createPage(parentId, emoji) override suspend fun closePage(id: String) { factory.remote.closePage(id) diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataStore.kt b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataStore.kt index c8e5b4d41a..6382984157 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataStore.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockDataStore.kt @@ -26,7 +26,7 @@ interface BlockDataStore { suspend fun move(command: CommandEntity.Move): PayloadEntity suspend fun unlink(command: CommandEntity.Unlink): PayloadEntity suspend fun getConfig(): ConfigEntity - suspend fun createPage(parentId: String): String + suspend fun createPage(parentId: String, emoji: String?): String suspend fun openPage(id: String): PayloadEntity suspend fun openProfile(id: String): PayloadEntity suspend fun closePage(id: String) diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemote.kt b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemote.kt index abd3e63719..1dd6a2be1e 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemote.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemote.kt @@ -24,7 +24,7 @@ interface BlockRemote { suspend fun updateCheckbox(command: CommandEntity.UpdateCheckbox) suspend fun move(command: CommandEntity.Move): PayloadEntity suspend fun getConfig(): ConfigEntity - suspend fun createPage(parentId: String): String + suspend fun createPage(parentId: String, emoji: String?): String suspend fun openPage(id: String): PayloadEntity suspend fun openProfile(id: String): PayloadEntity suspend fun closePage(id: String) diff --git a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemoteDataStore.kt b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemoteDataStore.kt index c17fad6324..eebadde57b 100644 --- a/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemoteDataStore.kt +++ b/data/src/main/java/com/agileburo/anytype/data/auth/repo/block/BlockRemoteDataStore.kt @@ -16,7 +16,8 @@ class BlockRemoteDataStore(private val remote: BlockRemote) : BlockDataStore { remote.closeDashboard(id = id) } - override suspend fun createPage(parentId: String): String = remote.createPage(parentId) + override suspend fun createPage(parentId: String, emoji: String?): String = + remote.createPage(parentId, emoji) override suspend fun openPage(id: String): PayloadEntity = remote.openPage(id) override suspend fun openProfile(id: String): PayloadEntity = remote.openProfile(id) diff --git a/domain/src/main/java/com/agileburo/anytype/domain/block/model/Command.kt b/domain/src/main/java/com/agileburo/anytype/domain/block/model/Command.kt index 3c202ac5fe..e3670b1eaf 100644 --- a/domain/src/main/java/com/agileburo/anytype/domain/block/model/Command.kt +++ b/domain/src/main/java/com/agileburo/anytype/domain/block/model/Command.kt @@ -134,12 +134,14 @@ sealed class Command { * @property target id of the block associated with the block we need to create * @property position position of the block that we need to create in relation with the target block * @property prototype a prototype of the block we would like to create + * @property emoji random emoji for new page */ class CreateDocument( val context: Id, val target: Id, val position: Position, - val prototype: Block.Prototype.Page + val prototype: Block.Prototype.Page, + val emoji: String? ) class Move( diff --git a/domain/src/main/java/com/agileburo/anytype/domain/block/repo/BlockRepository.kt b/domain/src/main/java/com/agileburo/anytype/domain/block/repo/BlockRepository.kt index 496c44de5c..1abba95a4e 100644 --- a/domain/src/main/java/com/agileburo/anytype/domain/block/repo/BlockRepository.kt +++ b/domain/src/main/java/com/agileburo/anytype/domain/block/repo/BlockRepository.kt @@ -65,7 +65,7 @@ interface BlockRepository { suspend fun getConfig(): Config @Deprecated("Should be replaced by createDocument() command") - suspend fun createPage(parentId: String): Id + suspend fun createPage(parentId: String, emoji: String? = null): Id suspend fun openPage(id: String): Payload suspend fun openProfile(id: String) : Payload diff --git a/domain/src/main/java/com/agileburo/anytype/domain/icon/DocumentEmojiIconProvider.kt b/domain/src/main/java/com/agileburo/anytype/domain/icon/DocumentEmojiIconProvider.kt new file mode 100644 index 0000000000..4970f4446b --- /dev/null +++ b/domain/src/main/java/com/agileburo/anytype/domain/icon/DocumentEmojiIconProvider.kt @@ -0,0 +1,5 @@ +package com.agileburo.anytype.domain.icon + +interface DocumentEmojiIconProvider { + fun random(): String +} \ No newline at end of file diff --git a/domain/src/main/java/com/agileburo/anytype/domain/page/CreateDocument.kt b/domain/src/main/java/com/agileburo/anytype/domain/page/CreateDocument.kt index 5c611b0bfa..af56d08d68 100644 --- a/domain/src/main/java/com/agileburo/anytype/domain/page/CreateDocument.kt +++ b/domain/src/main/java/com/agileburo/anytype/domain/page/CreateDocument.kt @@ -8,13 +8,15 @@ import com.agileburo.anytype.domain.block.model.Position import com.agileburo.anytype.domain.block.repo.BlockRepository import com.agileburo.anytype.domain.common.Id import com.agileburo.anytype.domain.event.model.Payload +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider /** * Use-case for creating a new document. * Should return a pair of ids, where the first one is block id, the second one is target id. */ class CreateDocument( - private val repo: BlockRepository + private val repo: BlockRepository, + private val documentEmojiProvider: DocumentEmojiIconProvider ) : BaseUseCase() { override suspend fun run(params: Params) = try { @@ -23,7 +25,8 @@ class CreateDocument( context = params.context, target = params.target, prototype = params.prototype, - position = params.position + position = params.position, + emoji = documentEmojiProvider.random() ) ).let { (id, target, payload) -> Either.Right( diff --git a/domain/src/main/java/com/agileburo/anytype/domain/page/CreatePage.kt b/domain/src/main/java/com/agileburo/anytype/domain/page/CreatePage.kt index 16c07de3a0..6d569a6f9c 100644 --- a/domain/src/main/java/com/agileburo/anytype/domain/page/CreatePage.kt +++ b/domain/src/main/java/com/agileburo/anytype/domain/page/CreatePage.kt @@ -5,24 +5,32 @@ import com.agileburo.anytype.domain.base.Either import com.agileburo.anytype.domain.block.repo.BlockRepository import com.agileburo.anytype.domain.common.Id import com.agileburo.anytype.domain.config.MainConfig +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider /** * A use-case for creating a new page. * Currently used for creating a new page inside a dashboard. */ class CreatePage( - private val repo: BlockRepository + private val repo: BlockRepository, + private val documentEmojiIconProvider: DocumentEmojiIconProvider ) : BaseUseCase() { override suspend fun run(params: Params) = try { if (params.id == MainConfig.HOME_DASHBOARD_ID) { repo.getConfig().let { config -> - repo.createPage(config.home).let { + repo.createPage( + parentId = config.home, + emoji = documentEmojiIconProvider.random() + ).let { Either.Right(it) } } } else { - repo.createPage(params.id).let { + repo.createPage( + parentId = params.id, + emoji = documentEmojiIconProvider.random() + ).let { Either.Right(it) } } diff --git a/library-emojifier/src/main/java/com/agileburo/anytype/emojifier/data/DefaultDocumentEmojiIconProvider.kt b/library-emojifier/src/main/java/com/agileburo/anytype/emojifier/data/DefaultDocumentEmojiIconProvider.kt new file mode 100644 index 0000000000..68cbb68d6f --- /dev/null +++ b/library-emojifier/src/main/java/com/agileburo/anytype/emojifier/data/DefaultDocumentEmojiIconProvider.kt @@ -0,0 +1,24 @@ +package com.agileburo.anytype.emojifier.data + +import com.agileburo.anytype.domain.icon.DocumentEmojiIconProvider + +class DefaultDocumentEmojiIconProvider : DocumentEmojiIconProvider { + + companion object { + val DOCUMENT_SET = listOf( + "🌳", "⛳", "🧬", "🎈", "🎓", + "💡", "🎒", "🚀", "🤖", "📚", + "🍎", "🏡", "🤝", "😍", "☕", + "🔥", "💥", "✍", "⏳", "📌", + "🚩", "🦉", "📮", "📄", "🖌", + "🗳", "⏰", "🔑", "🎉", "🗃", + "🔖", "🧠", "👁", "🎗", "🎲", + "🧩", "🚲", "⚙", "🔶", "🌍", + "🏕", "🧳", "🌵", "🚗", "🚂", + "🖼", "⭐", "🥁", "🚠", "🛫", + "🏔", "🏗", "🛠", "🔍", "🕹" + ) + } + + override fun random(): String = DOCUMENT_SET.random() +} \ No newline at end of file diff --git a/middleware/src/main/java/com/agileburo/anytype/middleware/block/BlockMiddleware.kt b/middleware/src/main/java/com/agileburo/anytype/middleware/block/BlockMiddleware.kt index f15f2261c2..b9f47326ba 100644 --- a/middleware/src/main/java/com/agileburo/anytype/middleware/block/BlockMiddleware.kt +++ b/middleware/src/main/java/com/agileburo/anytype/middleware/block/BlockMiddleware.kt @@ -21,7 +21,8 @@ class BlockMiddleware( middleware.closeDashboard(id) } - override suspend fun createPage(parentId: String): String = middleware.createPage(parentId) + override suspend fun createPage(parentId: String, emoji: String?): String = + middleware.createPage(parentId, emoji) override suspend fun openPage(id: String): PayloadEntity = middleware.openBlock(id) override suspend fun openProfile(id: String): PayloadEntity = middleware.openBlock(id) diff --git a/middleware/src/main/java/com/agileburo/anytype/middleware/interactor/Middleware.java b/middleware/src/main/java/com/agileburo/anytype/middleware/interactor/Middleware.java index 59dee2316e..eb57e39725 100644 --- a/middleware/src/main/java/com/agileburo/anytype/middleware/interactor/Middleware.java +++ b/middleware/src/main/java/com/agileburo/anytype/middleware/interactor/Middleware.java @@ -11,6 +11,7 @@ import com.agileburo.anytype.middleware.model.CreateAccountResponse; import com.agileburo.anytype.middleware.model.CreateWalletResponse; import com.agileburo.anytype.middleware.model.SelectAccountResponse; import com.agileburo.anytype.middleware.service.MiddlewareService; +import com.google.protobuf.Struct; import com.google.protobuf.Value; import java.util.List; @@ -229,10 +230,29 @@ public class Middleware { return mapper.toPayload(response.getEvent()); } - public String createPage(String parentId) throws Exception { + public String createPage(String parentId, String emoji) throws Exception { + + Value emojiValue = null; + + if (emoji != null) { + emojiValue = Value.newBuilder().setStringValue(emoji).build(); + } + + Struct details; + + if (emojiValue != null) { + details = Struct + .newBuilder() + .putFields(iconEmojiKey, emojiValue) + .build(); + } else { + details = Struct.getDefaultInstance(); + } + Block.CreatePage.Request request = Block.CreatePage.Request .newBuilder() .setContextId(parentId) + .setDetails(details) .setPosition(Models.Block.Position.Inner) .build(); @@ -534,6 +554,23 @@ public class Middleware { public Triple createDocument(CommandEntity.CreateDocument command) throws Exception { + Value emojiValue = null; + + if (command.getEmoji() != null) { + emojiValue = Value.newBuilder().setStringValue(command.getEmoji()).build(); + } + + Struct details; + + if (emojiValue != null) { + details = Struct + .newBuilder() + .putFields(iconEmojiKey, emojiValue) + .build(); + } else { + details = Struct.getDefaultInstance(); + } + Models.Block.Position position = mapper.toMiddleware(command.getPosition()); Block.CreatePage.Request request = Block.CreatePage.Request @@ -541,6 +578,7 @@ public class Middleware { .setContextId(command.getContext()) .setTargetId(command.getTarget()) .setPosition(position) + .setDetails(details) .build(); if (BuildConfig.DEBUG) { diff --git a/middleware/src/test/java/com/agileburo/anytype/MiddlewareTest.kt b/middleware/src/test/java/com/agileburo/anytype/MiddlewareTest.kt index 683c2366dd..e88ea7c0f3 100644 --- a/middleware/src/test/java/com/agileburo/anytype/MiddlewareTest.kt +++ b/middleware/src/test/java/com/agileburo/anytype/MiddlewareTest.kt @@ -11,6 +11,7 @@ import com.agileburo.anytype.middleware.interactor.Middleware import com.agileburo.anytype.middleware.interactor.MiddlewareFactory import com.agileburo.anytype.middleware.interactor.MiddlewareMapper import com.agileburo.anytype.middleware.service.MiddlewareService +import com.google.protobuf.Struct import com.google.protobuf.Value import com.nhaarman.mockitokotlin2.* import org.junit.Before @@ -66,7 +67,8 @@ class MiddlewareTest { prototype = BlockEntity.Prototype.Page( style = BlockEntity.Content.Page.Style.EMPTY ), - position = PositionEntity.INNER + position = PositionEntity.INNER, + emoji = null ) val response = Block.CreatePage.Response @@ -80,6 +82,66 @@ class MiddlewareTest { .setContextId(command.context) .setTargetId(command.target) .setPosition(Models.Block.Position.Inner) + .setDetails(Struct.getDefaultInstance()) + .build() + + service.stub { + on { blockCreatePage(any()) } doReturn response + } + + // TESTING + + val (block, target) = middleware.createDocument(command) + + verify(service, times(1)).blockCreatePage(request) + + assertEquals( + expected = response.blockId, + actual = block + ) + + assertEquals( + expected = response.targetId, + actual = target + ) + } + + @Test + fun `should create request to create new document with emoji`() { + + // SETUP + + val emoji = "🎒" + + val command = CommandEntity.CreateDocument( + context = MockDataFactory.randomUuid(), + target = MockDataFactory.randomUuid(), + prototype = BlockEntity.Prototype.Page( + style = BlockEntity.Content.Page.Style.EMPTY + ), + position = PositionEntity.INNER, + emoji = emoji + ) + + val response = Block.CreatePage.Response + .newBuilder() + .setBlockId(MockDataFactory.randomUuid()) + .setTargetId(MockDataFactory.randomUuid()) + .build() + + val request = Block.CreatePage.Request + .newBuilder() + .setContextId(command.context) + .setTargetId(command.target) + .setPosition(Models.Block.Position.Inner) + .setDetails( + Struct.newBuilder() + .putFields( + "iconEmoji", + Value.newBuilder().setStringValue(emoji).build() + ) + .build() + ) .build() service.stub {