1
0
Fork 0
mirror of https://github.com/anyproto/anytype-kotlin.git synced 2025-06-07 21:37:02 +09:00

DROID-2793 Date as an Object | Epic (#1782)

Co-authored-by: Evgenii Kozlov <enklave.mare.balticum@protonmail.com>
Co-authored-by: Evgenii Kozlov <ubuphobos@gmail.com>
This commit is contained in:
Konstantin Ivanov 2024-12-04 16:06:16 +01:00 committed by GitHub
parent 2b40f21910
commit ca8721b725
Signed by: github
GPG key ID: B5690EEEBB952194
284 changed files with 6589 additions and 1211 deletions

View file

@ -289,6 +289,7 @@ object EventsDictionary {
const val searchMenu = "MenuSearch"
const val objCreateSet = "Set"
const val objCreateHome = "Home"
const val objDate = "Date"
const val objCreateCollection = "Collection"
const val allContentRoute = "Library"
const val objCreateMention = "Mention"

View file

@ -176,6 +176,7 @@ dependencies {
implementation project(':feature-discussions')
implementation project(':gallery-experience')
implementation project(':feature-all-content')
implementation project(':feature-date')
//Compile time dependencies
ksp libs.daggerCompiler

View file

@ -61,6 +61,7 @@ import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvid
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
@ -69,6 +70,7 @@ import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.page.CloseBlock
@ -80,6 +82,7 @@ import com.anytypeio.anytype.domain.page.Redo
import com.anytypeio.anytype.domain.page.Undo
import com.anytypeio.anytype.domain.page.bookmark.CreateBookmarkBlock
import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.SetRelationKey
import com.anytypeio.anytype.domain.search.SearchObjects
@ -148,6 +151,9 @@ open class EditorTestSetup {
@Mock
lateinit var documentFileShareDownloader: DocumentFileShareDownloader
@Mock
lateinit var dateProvider: DateProvider
@Mock
lateinit var openPage: OpenPage
@ -276,6 +282,9 @@ open class EditorTestSetup {
@Mock
lateinit var fileLimitsEventChannel: FileLimitsEventChannel
@Mock
lateinit var getDateObjectByTimestamp: GetDateObjectByTimestamp
@Mock
lateinit var spaceManager: SpaceManager
@ -294,6 +303,9 @@ open class EditorTestSetup {
@Mock
lateinit var spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
@Mock
lateinit var fieldParser: FieldParser
lateinit var interceptFileLimitEvents: InterceptFileLimitEvents
lateinit var addRelationToObject: AddRelationToObject
@ -410,7 +422,8 @@ open class EditorTestSetup {
toggleStateHolder = ToggleStateHolder.Default(),
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
storeOfObjectTypes = storeOfObjectTypes,
fieldParser = fieldParser
),
orchestrator = Orchestrator(
createBlock = createBlock,
@ -496,7 +509,10 @@ open class EditorTestSetup {
syncStatusProvider = spaceSyncAndP2PStatusProvider,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
clearLastOpenedObject = clearLastOpenedObject,
getNetworkMode = getNetworkMode
getNetworkMode = getNetworkMode,
fieldParser = fieldParser,
dateProvider = dateProvider,
getDateObjectByTimestamp = getDateObjectByTimestamp,
)
}

View file

@ -24,6 +24,7 @@ import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
@ -105,6 +106,9 @@ class ObjectRelationListTest {
lateinit var urlBuilder: UrlBuilder
@Mock
lateinit var fieldParser: FieldParser
@Before
fun setup() {
MockitoAnnotations.openMocks(this)
@ -126,7 +130,8 @@ class ObjectRelationListTest {
storeOfRelations = storeOfRelations,
addRelationToObject = addRelationToObject,
spaceManager = spaceManager,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
fieldParser = fieldParser
)
}

View file

@ -48,6 +48,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.CancelSearchSubscription
import com.anytypeio.anytype.domain.search.DataViewSubscriptionContainer
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
@ -57,6 +58,7 @@ import com.anytypeio.anytype.domain.templates.CreateTemplate
import com.anytypeio.anytype.domain.templates.GetTemplates
import com.anytypeio.anytype.domain.unsplash.DownloadUnsplashImage
import com.anytypeio.anytype.domain.unsplash.UnsplashRepository
import com.anytypeio.anytype.domain.vault.ObserveVaultSettings
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.emojifier.data.DefaultDocumentEmojiIconProvider
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
@ -79,12 +81,12 @@ import java.util.Locale
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.stub
abstract class TestObjectSetSetup {
@ -231,7 +233,18 @@ abstract class TestObjectSetSetup {
@Mock
lateinit var localeProvider : LocaleProvider
private val dateProvider = DateProviderImpl(ZoneId.systemDefault(), localeProvider)
@Mock
lateinit var observeVaultSettings: ObserveVaultSettings
@Mock
lateinit var fieldParser: FieldParser
private val dateProvider = DateProviderImpl(
defaultZoneId = ZoneId.systemDefault(),
localeProvider = localeProvider,
vaultSettings = observeVaultSettings,
scope = TestScope()
)
open fun setup() {
MockitoAnnotations.openMocks(this)
@ -317,7 +330,8 @@ abstract class TestObjectSetSetup {
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider,
clearLastOpenedObject = clearLastOpenedObject
clearLastOpenedObject = clearLastOpenedObject,
fieldParser = fieldParser
)
Mockito.`when`(localeProvider.locale()).thenReturn(Locale.getDefault())

View file

@ -25,6 +25,7 @@ import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -73,6 +74,9 @@ class CreateSelectedFilterTest {
@Mock
lateinit var dispatchers: AppCoroutineDispatchers
@Mock
lateinit var fieldParser: FieldParser
private lateinit var updateDataViewViewer: UpdateDataViewViewer
private lateinit var searchObjects: SearchObjects
private lateinit var getOptions: GetOptions
@ -104,7 +108,8 @@ class CreateSelectedFilterTest {
storeOfRelations = storeOfRelations,
objectSetDatabase = db,
getOptions = getOptions,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.relations.ObjectSetConfig
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -64,6 +65,9 @@ class FilterListTest {
@Mock
lateinit var dispatchers: AppCoroutineDispatchers
@Mock
lateinit var fieldParser: FieldParser
lateinit var updateDataViewViewer: UpdateDataViewViewer
lateinit var searchObjects: SearchObjects
lateinit var urlBuilder: UrlBuilder
@ -88,7 +92,8 @@ class FilterListTest {
state = state,
analytics = analytics,
storeOfRelations = storeOfRelations,
objectSetDatabase = db
objectSetDatabase = db,
fieldParser = fieldParser
)
}

View file

@ -33,6 +33,7 @@ import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -78,6 +79,9 @@ class ModifyInputValueFilterTest {
@Mock
lateinit var spaceManager: SpaceManager
@Mock
lateinit var fieldParser: FieldParser
private lateinit var updateDataViewViewer: UpdateDataViewViewer
private lateinit var searchObjects: SearchObjects
private lateinit var getOptions: GetOptions
@ -108,7 +112,8 @@ class ModifyInputValueFilterTest {
storeOfRelations = storeOfRelations,
objectSetDatabase = db,
getOptions = getOptions,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -31,6 +31,7 @@ import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -74,6 +75,9 @@ class ModifyStatusFilterTest {
@Mock
lateinit var analytics: Analytics
@Mock
lateinit var fieldParser: FieldParser
@Mock
lateinit var spaceManager: SpaceManager
@ -108,7 +112,8 @@ class ModifyStatusFilterTest {
analytics = analytics,
storeOfRelations = storeOfRelations,
objectSetDatabase = db,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -31,6 +31,7 @@ import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -76,6 +77,9 @@ class ModifyTagFilterTest {
@Mock
lateinit var spaceManager: SpaceManager
@Mock
lateinit var fieldParser: FieldParser
private lateinit var updateDataViewViewer: UpdateDataViewViewer
private lateinit var searchObjects: SearchObjects
private lateinit var getOptions: GetOptions
@ -107,7 +111,8 @@ class ModifyTagFilterTest {
storeOfRelations = storeOfRelations,
objectSetDatabase = db,
getOptions = getOptions,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.di.feature.CreateObjectModule
import com.anytypeio.anytype.di.feature.DaggerAllContentComponent
import com.anytypeio.anytype.di.feature.DaggerAppPreferencesComponent
import com.anytypeio.anytype.di.feature.DaggerBacklinkOrAddToObjectComponent
import com.anytypeio.anytype.di.feature.DaggerDateObjectComponent
import com.anytypeio.anytype.di.feature.DaggerLinkToObjectComponent
import com.anytypeio.anytype.di.feature.DaggerMoveToComponent
import com.anytypeio.anytype.di.feature.DaggerSplashComponent
@ -100,9 +101,9 @@ import com.anytypeio.anytype.di.feature.widgets.DaggerSelectWidgetSourceComponen
import com.anytypeio.anytype.di.feature.widgets.DaggerSelectWidgetTypeComponent
import com.anytypeio.anytype.di.main.MainComponent
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModel
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectVmParams
import com.anytypeio.anytype.feature_discussions.presentation.DiscussionViewModel
import com.anytypeio.anytype.gallery_experience.viewmodel.GalleryInstallationViewModel
import com.anytypeio.anytype.presentation.common.BaseViewModel
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.history.VersionHistoryViewModel
import com.anytypeio.anytype.presentation.linking.LinkToObjectOrWebViewModel
@ -337,6 +338,12 @@ class ComponentManager(
.create(params, findComponentDependencies())
}
val dateObjectComponent = ComponentWithParams { params: DateObjectVmParams ->
DaggerDateObjectComponent
.factory()
.create(params, findComponentDependencies())
}
val objectSetComponent = ComponentMapWithParam { param: DefaultComponentParam ->
main.objectSetComponentBuilder()
.module(ObjectSetModule)

View file

@ -8,7 +8,6 @@ import com.anytypeio.anytype.domain.all_content.RestoreAllContentState
import com.anytypeio.anytype.domain.all_content.UpdateAllContentState
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.debugging.Logger
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
@ -20,10 +19,10 @@ import com.anytypeio.anytype.domain.`object`.SetObjectDetails
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.workspace.RemoveObjectsFromWorkspace
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModel
import com.anytypeio.anytype.feature_allcontent.presentation.AllContentViewModelFactory
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
@ -100,8 +99,7 @@ object AllContentModule {
fun createObject(
repo: BlockRepository,
getDefaultObjectType: GetDefaultObjectType,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager,
dispatchers: AppCoroutineDispatchers
): CreateObject = CreateObject(
repo = repo,
getDefaultObjectType = getDefaultObjectType,
@ -114,9 +112,7 @@ object AllContentModule {
fun provideGetDefaultPageType(
userSettingsRepository: UserSettingsRepository,
blockRepository: BlockRepository,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager,
configStorage: ConfigStorage
dispatchers: AppCoroutineDispatchers
): GetDefaultObjectType = GetDefaultObjectType(
userSettingsRepository = userSettingsRepository,
blockRepository = blockRepository,
@ -169,8 +165,7 @@ interface AllContentDependencies : ComponentDependencies {
fun subEventChannel(): SubscriptionEventChannel
fun logger(): Logger
fun localeProvider(): LocaleProvider
fun spaceManager(): SpaceManager
fun config(): ConfigStorage
fun userPermissionProvider(): UserPermissionProvider
fun searchObjects(): SearchObjects
fun fieldsProvider(): FieldParser
}

View file

@ -8,7 +8,9 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.linking.BackLinkOrAddToObjectViewModelFactory
@ -73,4 +75,6 @@ interface BacklinkOrAddToObjectDependencies : ComponentDependencies {
fun analytics(): Analytics
fun analyticSpaceHelper(): AnalyticSpaceHelperDelegate
fun searchObjects(): SearchObjects
fun dateProvider(): DateProvider
fun fieldParser(): FieldParser
}

View file

@ -0,0 +1,173 @@
package com.anytypeio.anytype.di.feature
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.debugging.Logger
import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvider
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.LocaleProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.`object`.GetObject
import com.anytypeio.anytype.domain.`object`.SetObjectDetails
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.GetObjectRelationListById
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectVMFactory
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectVmParams
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.ui.date.DateObjectFragment
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import dagger.Provides
@Component(
dependencies = [DateObjectDependencies::class],
modules = [
DateObjectModule::class,
DateObjectModule.Declarations::class
]
)
@PerScreen
interface DateObjectComponent {
@Component.Factory
interface Factory {
fun create(
@BindsInstance vmParams: DateObjectVmParams,
dependencies: DateObjectDependencies
): DateObjectComponent
}
fun inject(fragment: DateObjectFragment)
}
@Module
object DateObjectModule {
@JvmStatic
@Provides
@PerScreen
fun getObject(
repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
): GetObject = GetObject(
repo = repo,
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun provideStoreLessSubscriptionContainer(
repo: BlockRepository,
channel: SubscriptionEventChannel,
dispatchers: AppCoroutineDispatchers,
logger: Logger
): StorelessSubscriptionContainer = StorelessSubscriptionContainer.Impl(
repo = repo,
channel = channel,
dispatchers = dispatchers,
logger = logger
)
@JvmStatic
@Provides
@PerScreen
fun searchObjects(
repo: BlockRepository
): SearchObjects = SearchObjects(repo = repo)
@JvmStatic
@Provides
@PerScreen
fun createObject(
repo: BlockRepository,
getDefaultObjectType: GetDefaultObjectType,
dispatchers: AppCoroutineDispatchers,
): CreateObject = CreateObject(
repo = repo,
getDefaultObjectType = getDefaultObjectType,
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun provideGetDefaultPageType(
userSettingsRepository: UserSettingsRepository,
blockRepository: BlockRepository,
dispatchers: AppCoroutineDispatchers
): GetDefaultObjectType = GetDefaultObjectType(
userSettingsRepository = userSettingsRepository,
blockRepository = blockRepository,
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun provideRelationListWithValue(
repository: BlockRepository,
dispatchers: AppCoroutineDispatchers
): GetObjectRelationListById = GetObjectRelationListById(repository, dispatchers)
@JvmStatic
@Provides
@PerScreen
fun provideUpdateDetailUseCase(
repository: BlockRepository,
dispatchers: AppCoroutineDispatchers
): SetObjectDetails = SetObjectDetails(repository, dispatchers)
@JvmStatic
@Provides
@PerScreen
fun provideDateByTimestamp(
repository: BlockRepository,
dispatchers: AppCoroutineDispatchers
): GetDateObjectByTimestamp = GetDateObjectByTimestamp(repository, dispatchers)
@Module
interface Declarations {
@PerScreen
@Binds
fun bindViewModelFactory(
factory: DateObjectVMFactory
): ViewModelProvider.Factory
}
}
interface DateObjectDependencies : ComponentDependencies {
fun blockRepository(): BlockRepository
fun analytics(): Analytics
fun urlBuilder(): UrlBuilder
fun dispatchers(): AppCoroutineDispatchers
fun storeOfObjectTypes(): StoreOfObjectTypes
fun analyticsHelper(): AnalyticSpaceHelperDelegate
fun subEventChannel(): SubscriptionEventChannel
fun logger(): Logger
fun localeProvider(): LocaleProvider
fun config(): ConfigStorage
fun userPermissionProvider(): UserPermissionProvider
fun provideStoreOfRelations(): StoreOfRelations
fun provideDateProvider(): DateProvider
fun provideSpaceSyncAndP2PStatusProvider(): SpaceSyncAndP2PStatusProvider
fun provideUserSettingsRepository(): UserSettingsRepository
fun fieldParser(): FieldParser
}

View file

@ -55,6 +55,7 @@ import com.anytypeio.anytype.domain.event.interactor.SpaceSyncAndP2PStatusProvid
import com.anytypeio.anytype.domain.icon.SetDocumentImageIcon
import com.anytypeio.anytype.domain.launch.GetDefaultObjectType
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.multiplayer.UserPermissionProvider
import com.anytypeio.anytype.domain.networkmode.GetNetworkMode
@ -62,6 +63,7 @@ import com.anytypeio.anytype.domain.`object`.ConvertObjectToCollection
import com.anytypeio.anytype.domain.`object`.ConvertObjectToSet
import com.anytypeio.anytype.domain.`object`.DuplicateObject
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.GetDateObjectByTimestamp
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
@ -75,6 +77,7 @@ import com.anytypeio.anytype.domain.page.Undo
import com.anytypeio.anytype.domain.page.UpdateTitle
import com.anytypeio.anytype.domain.page.bookmark.CreateBookmarkBlock
import com.anytypeio.anytype.domain.page.bookmark.SetupBookmark
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.AddFileToObject
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.SetRelationKey
@ -287,7 +290,10 @@ object EditorSessionModule {
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
syncStatusProvider: SpaceSyncAndP2PStatusProvider,
getNetworkMode: GetNetworkMode,
clearLastOpenedObject: ClearLastOpenedObject
clearLastOpenedObject: ClearLastOpenedObject,
fieldParser: FieldParser,
dateProvider: DateProvider,
getDateObjectByTimestamp: GetDateObjectByTimestamp
): EditorViewModelFactory = EditorViewModelFactory(
params = params,
permissions = permissions,
@ -333,7 +339,10 @@ object EditorSessionModule {
getNetworkMode = getNetworkMode,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
clearLastOpenedObject = clearLastOpenedObject,
syncStatusProvider = syncStatusProvider
syncStatusProvider = syncStatusProvider,
fieldParser = fieldParser,
dateProvider = dateProvider,
getDateObjectByTimestamp = getDateObjectByTimestamp
)
@JvmStatic
@ -374,13 +383,15 @@ object EditorSessionModule {
toggleStateHolder: ToggleStateHolder,
coverImageHashProvider: CoverImageHashProvider,
storeOfRelations: StoreOfRelations,
storeOfObjectTypes: StoreOfObjectTypes
storeOfObjectTypes: StoreOfObjectTypes,
fieldParser: FieldParser
): DefaultBlockViewRenderer = DefaultBlockViewRenderer(
urlBuilder = urlBuilder,
toggleStateHolder = toggleStateHolder,
coverImageHashProvider = coverImageHashProvider,
storeOfRelations = storeOfRelations,
storeOfObjectTypes = storeOfObjectTypes
storeOfObjectTypes = storeOfObjectTypes,
fieldParser = fieldParser
)
@JvmStatic
@ -1160,4 +1171,12 @@ object EditorUseCaseModule {
getDefaultObjectType = getDefaultObjectType,
dispatchers = dispatchers
)
@JvmStatic
@Provides
@PerScreen
fun provideDateByTimestamp(
repository: BlockRepository,
dispatchers: AppCoroutineDispatchers
): GetDateObjectByTimestamp = GetDateObjectByTimestamp(repository, dispatchers)
}

View file

@ -4,7 +4,9 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.linking.LinkToObjectViewModelFactory
@ -40,6 +42,8 @@ interface LinkToObjectDependencies: ComponentDependencies {
fun searchObjects(): SearchObjects
fun analytics(): Analytics
fun analyticSpaceHelperDelegate(): AnalyticSpaceHelperDelegate
fun dateProvider(): DateProvider
fun fieldParser(): FieldParser
}
@ -55,13 +59,15 @@ object LinkToObjectModule {
getObjectTypes: GetObjectTypes,
searchObjects: SearchObjects,
analytics: Analytics,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
fieldParser: FieldParser
): LinkToObjectViewModelFactory = LinkToObjectViewModelFactory(
vmParams = vmParams,
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
fieldParser = fieldParser
)
}

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_utils.di.scope.PerModal
import com.anytypeio.anytype.core_utils.tools.UrlValidator
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.editor.Editor
@ -47,7 +48,8 @@ object LinkToObjectOrWebModule {
analytics: Analytics,
stores: Editor.Storage,
urlValidator: UrlValidator,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
fieldParser: FieldParser
): LinkToObjectOrWebViewModelFactory = LinkToObjectOrWebViewModelFactory(
vmParams = vmParams,
urlBuilder = urlBuilder,
@ -56,6 +58,7 @@ object LinkToObjectOrWebModule {
analytics = analytics,
stores = stores,
urlValidator = urlValidator,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
fieldParser = fieldParser
)
}

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.moving.MoveToViewModel
@ -40,6 +41,7 @@ interface MoveToDependencies : ComponentDependencies {
fun searchObjects(): SearchObjects
fun analytics(): Analytics
fun analyticSpaceHelperDelegate(): AnalyticSpaceHelperDelegate
fun fieldParser(): FieldParser
}
@Module
@ -54,13 +56,15 @@ object MoveToModule {
getObjectTypes: GetObjectTypes,
searchObjects: SearchObjects,
analytics: Analytics,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
fieldParser: FieldParser
): MoveToViewModelFactory = MoveToViewModelFactory(
vmParams = vmParams,
urlBuilder = urlBuilder,
getObjectTypes = getObjectTypes,
searchObjects = searchObjects,
analytics = analytics,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
fieldParser = fieldParser
)
}

View file

@ -12,6 +12,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.collections.AddObjectToCollection
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.dashboard.interactor.SetObjectListIsFavorite
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.DeepLinkResolver
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.DuplicateObject
@ -20,6 +21,7 @@ import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.page.AddBackLinkToObject
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.OpenPage
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.templates.CreateTemplateFromObject
import com.anytypeio.anytype.domain.widgets.CreateWidget
import com.anytypeio.anytype.domain.workspace.SpaceManager
@ -116,7 +118,8 @@ object ObjectMenuModule {
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
payloadDelegator: PayloadDelegator,
setObjectListIsFavorite: SetObjectListIsFavorite,
setObjectIsArchived: SetObjectListIsArchived
setObjectIsArchived: SetObjectListIsArchived,
fieldParser: FieldParser
): ObjectMenuViewModel.Factory = ObjectMenuViewModel.Factory(
setObjectIsArchived = setObjectIsArchived,
duplicateObject = duplicateObject,
@ -138,7 +141,8 @@ object ObjectMenuModule {
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
payloadDelegator = payloadDelegator,
setObjectListIsFavorite = setObjectListIsFavorite
setObjectListIsFavorite = setObjectListIsFavorite,
fieldParser = fieldParser
)
@JvmStatic
@ -231,7 +235,8 @@ object ObjectSetMenuModule {
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
payloadDelegator: PayloadDelegator,
setObjectListIsFavorite: SetObjectListIsFavorite,
setObjectIsArchived: SetObjectListIsArchived
setObjectIsArchived: SetObjectListIsArchived,
fieldParser: FieldParser,
): ObjectSetMenuViewModel.Factory = ObjectSetMenuViewModel.Factory(
setObjectListIsArchived = setObjectIsArchived,
addBackLinkToObject = addBackLinkToObject,
@ -249,7 +254,8 @@ object ObjectSetMenuModule {
deepLinkResolver = deepLinkResolver,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
payloadDelegator = payloadDelegator,
setObjectListIsFavorite = setObjectListIsFavorite
setObjectListIsFavorite = setObjectListIsFavorite,
fieldParser = fieldParser
)
@JvmStatic

View file

@ -7,6 +7,7 @@ import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.AddToFeaturedRelations
import com.anytypeio.anytype.domain.relations.DeleteRelationFromObject
@ -53,7 +54,8 @@ object ObjectRelationListModule {
storeOfRelations: StoreOfRelations,
addRelationToObject: AddRelationToObject,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
spaceManager: SpaceManager
spaceManager: SpaceManager,
fieldParser: FieldParser
): ObjectRelationListViewModelFactory {
return ObjectRelationListViewModelFactory(
lockedStateProvider = lockedStateProvider,
@ -68,7 +70,8 @@ object ObjectRelationListModule {
storeOfRelations = storeOfRelations,
addRelationToObject = addRelationToObject,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -50,6 +50,7 @@ import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.page.CloseBlock
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.relations.AddFileToObject
import com.anytypeio.anytype.domain.relations.AddRelationToObject
import com.anytypeio.anytype.domain.relations.DeleteRelationFromDataView
@ -232,7 +233,8 @@ object ObjectSetModule {
permissions: UserPermissionProvider,
clearLastOpenedObject: ClearLastOpenedObject,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider
spaceSyncAndP2PStatusProvider: SpaceSyncAndP2PStatusProvider,
fieldParser: FieldParser
): ObjectSetViewModelFactory = ObjectSetViewModelFactory(
params = params,
openObjectSet = openObjectSet,
@ -274,7 +276,8 @@ object ObjectSetModule {
permissions = permissions,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
spaceSyncAndP2PStatusProvider = spaceSyncAndP2PStatusProvider,
clearLastOpenedObject = clearLastOpenedObject
clearLastOpenedObject = clearLastOpenedObject,
fieldParser = fieldParser
)
@JvmStatic

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.domain.`object`.UpdateDetail
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
@ -71,7 +72,8 @@ object ObjectValueObjectModule {
objectListIsArchived: SetObjectListIsArchived,
duplicateObject: DuplicateObject,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
storeOfRelations: StoreOfRelations
storeOfRelations: StoreOfRelations,
fieldParser: FieldParser,
): ObjectValueViewModelFactory = ObjectValueViewModelFactory(
params = params,
values = values,
@ -86,7 +88,8 @@ object ObjectValueObjectModule {
objectListIsArchived = objectListIsArchived,
duplicateObject = duplicateObject,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
fieldParser = fieldParser
)
}
//endregion
@ -128,7 +131,8 @@ object ObjectValueSetModule {
objectListIsArchived: SetObjectListIsArchived,
duplicateObject: DuplicateObject,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
storeOfRelations: StoreOfRelations
storeOfRelations: StoreOfRelations,
fieldParser: FieldParser
): ObjectValueViewModelFactory = ObjectValueViewModelFactory(
params = params,
values = values,
@ -143,7 +147,8 @@ object ObjectValueSetModule {
objectListIsArchived = objectListIsArchived,
duplicateObject = duplicateObject,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
fieldParser = fieldParser
)
}
//endregion
@ -185,7 +190,8 @@ object ObjectValueDataViewModule {
objectListIsArchived: SetObjectListIsArchived,
duplicateObject: DuplicateObject,
analyticSpaceHelperDelegate: AnalyticSpaceHelperDelegate,
storeOfRelations: StoreOfRelations
storeOfRelations: StoreOfRelations,
fieldParser: FieldParser
): ObjectValueViewModelFactory = ObjectValueViewModelFactory(
params = params,
values = values,
@ -200,7 +206,8 @@ object ObjectValueDataViewModule {
objectListIsArchived = objectListIsArchived,
duplicateObject = duplicateObject,
analyticSpaceHelperDelegate = analyticSpaceHelperDelegate,
storeOfRelations = storeOfRelations
storeOfRelations = storeOfRelations,
fieldParser = fieldParser
)
}
//endregion

View file

@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.domain.dataview.interactor.UpdateDataViewViewer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
import com.anytypeio.anytype.presentation.sets.filter.ViewerFilterViewModel
import com.anytypeio.anytype.presentation.sets.state.ObjectState
@ -41,7 +42,8 @@ object ViewerFilterModule {
urlBuilder: UrlBuilder,
analytics: Analytics,
storeOfRelations: StoreOfRelations,
db: ObjectSetDatabase
db: ObjectSetDatabase,
fieldParser: FieldParser
): ViewerFilterViewModel.Factory = ViewerFilterViewModel.Factory(
state = state,
dispatcher = dispatcher,
@ -49,10 +51,11 @@ object ViewerFilterModule {
urlBuilder = urlBuilder,
analytics = analytics,
storeOfRelations = storeOfRelations,
objectSetDatabase = db
objectSetDatabase = db,
fieldParser = fieldParser
)
}
@Scope
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
@Retention(AnnotationRetention.RUNTIME)
annotation class ViewerFilterByScope

View file

@ -10,6 +10,7 @@ import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.search.GlobalSearchViewModel
import com.anytypeio.anytype.ui.search.GlobalSearchFragment
@ -58,4 +59,5 @@ interface GlobalSearchDependencies : ComponentDependencies {
fun analytics(): Analytics
fun analyticsHelper(): AnalyticSpaceHelperDelegate
fun userSettingsRepository(): UserSettingsRepository
fun fieldParser(): FieldParser
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -52,7 +53,8 @@ object CreateFilterModule {
objectSetDatabase: ObjectSetDatabase,
analytics: Analytics,
getOptions: GetOptions,
spaceManager: SpaceManager
spaceManager: SpaceManager,
fieldParser: FieldParser
): FilterViewModel.Factory = FilterViewModel.Factory(
objectState = state,
dispatcher = dispatcher,
@ -64,6 +66,7 @@ object CreateFilterModule {
objectSetDatabase = objectSetDatabase,
analytics = analytics,
getOptions = getOptions,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.objects.options.GetOptions
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sets.ObjectSetDatabase
@ -52,7 +53,8 @@ object ModifyFilterModule {
objectSetDatabase: ObjectSetDatabase,
getOptions: GetOptions,
storeOfRelations: StoreOfRelations,
spaceManager: SpaceManager
spaceManager: SpaceManager,
fieldParser: FieldParser
): FilterViewModel.Factory = FilterViewModel.Factory(
objectState = state,
dispatcher = dispatcher,
@ -64,6 +66,7 @@ object ModifyFilterModule {
storeOfRelations = storeOfRelations,
analytics = analytics,
getOptions = getOptions,
spaceManager = spaceManager
spaceManager = spaceManager,
fieldParser = fieldParser
)
}

View file

@ -2,9 +2,11 @@ package com.anytypeio.anytype.di.feature.templates
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.presentation.editor.cover.CoverImageHashProvider
import com.anytypeio.anytype.presentation.editor.render.DefaultBlockViewRenderer
import com.anytypeio.anytype.presentation.editor.toggle.ToggleStateHolder
@ -69,6 +71,8 @@ interface TemplateBlankDependencies : ComponentDependencies {
fun urlBuilder(): UrlBuilder
fun storeOfRelations(): StoreOfRelations
fun storeOfObjectTypes(): StoreOfObjectTypes
fun dateProvider(): DateProvider
fun fieldsProvider(): FieldParser
}
@Scope

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.SearchObjects
import com.anytypeio.anytype.presentation.analytics.AnalyticSpaceHelperDelegate
import com.anytypeio.anytype.presentation.search.ObjectSearchViewModel
@ -48,6 +49,7 @@ interface SelectWidgetSourceDependencies : ComponentDependencies {
fun storeOfObjectTypes(): StoreOfObjectTypes
fun analyticsHelper(): AnalyticSpaceHelperDelegate
fun searchObjects(): SearchObjects
fun fieldParser(): FieldParser
}
@Module
@ -63,7 +65,8 @@ object SelectWidgetSourceModule {
searchObjects: SearchObjects,
getObjectTypes: GetObjectTypes,
dispatcher: Dispatcher<WidgetDispatchEvent>,
analyticsHelper: AnalyticSpaceHelperDelegate
analyticsHelper: AnalyticSpaceHelperDelegate,
fieldParser: FieldParser
): SelectWidgetSourceViewModel.Factory = SelectWidgetSourceViewModel.Factory(
vmParams = vmParams,
urlBuilder = urlBuilder,
@ -71,6 +74,7 @@ object SelectWidgetSourceModule {
analytics = analytics,
getObjectTypes = getObjectTypes,
dispatcher = dispatcher,
analyticSpaceHelperDelegate = analyticsHelper
analyticSpaceHelperDelegate = analyticsHelper,
fieldParser = fieldParser
)
}

View file

@ -8,6 +8,7 @@ import com.anytypeio.anytype.di.feature.AppPreferencesDependencies
import com.anytypeio.anytype.di.feature.BacklinkOrAddToObjectDependencies
import com.anytypeio.anytype.di.feature.CreateBookmarkSubComponent
import com.anytypeio.anytype.di.feature.CreateObjectSubComponent
import com.anytypeio.anytype.di.feature.DateObjectDependencies
import com.anytypeio.anytype.di.feature.DebugSettingsSubComponent
import com.anytypeio.anytype.di.feature.EditorSubComponent
import com.anytypeio.anytype.di.feature.KeychainPhraseSubComponent
@ -133,7 +134,8 @@ interface MainComponent :
SelectWidgetSourceDependencies,
SelectWidgetTypeDependencies,
LinkToObjectDependencies,
MoveToDependencies
MoveToDependencies,
DateObjectDependencies
{
fun inject(app: AndroidApplication)
@ -379,4 +381,9 @@ abstract class ComponentDependenciesModule {
@IntoMap
@ComponentDependenciesKey(MoveToDependencies::class)
abstract fun provideMoveToDependencies(component: MainComponent): ComponentDependencies
@Binds
@IntoMap
@ComponentDependenciesKey(DateObjectDependencies::class)
abstract fun provideDateObjectDependencies(component: MainComponent): ComponentDependencies
}

View file

@ -14,6 +14,7 @@ import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.core_utils.tools.ThreadInfo
import com.anytypeio.anytype.core_utils.tools.UrlValidator
import com.anytypeio.anytype.device.providers.DateProviderImpl
import com.anytypeio.anytype.di.main.ConfigModule.DEFAULT_APP_COROUTINE_SCOPE
import com.anytypeio.anytype.domain.config.Gateway
import com.anytypeio.anytype.domain.debugging.DebugConfig
import com.anytypeio.anytype.domain.debugging.Logger
@ -21,6 +22,9 @@ import com.anytypeio.anytype.domain.misc.DateProvider
import com.anytypeio.anytype.domain.misc.DateTypeNameProvider
import com.anytypeio.anytype.domain.misc.LocaleProvider
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.primitives.FieldParserImpl
import com.anytypeio.anytype.domain.vault.ObserveVaultSettings
import com.anytypeio.anytype.middleware.interactor.MiddlewareProtobufLogger
import com.anytypeio.anytype.middleware.interactor.ProtobufConverterProvider
import com.anytypeio.anytype.other.BasicLogger
@ -30,7 +34,9 @@ import dagger.Binds
import dagger.Module
import dagger.Provides
import java.time.ZoneId
import javax.inject.Named
import javax.inject.Singleton
import kotlinx.coroutines.CoroutineScope
@Module(includes = [UtilModule.Bindings::class])
object UtilModule {
@ -57,12 +63,23 @@ object UtilModule {
@Provides
@Singleton
fun provideDateProvider(
localeProvider: LocaleProvider
): DateProvider =
DateProviderImpl(
defaultZoneId = ZoneId.systemDefault(),
localeProvider = localeProvider
)
localeProvider: LocaleProvider,
observeVaultSettings: ObserveVaultSettings,
@Named(DEFAULT_APP_COROUTINE_SCOPE) scope: CoroutineScope
): DateProvider = DateProviderImpl(
defaultZoneId = ZoneId.systemDefault(),
localeProvider = localeProvider,
vaultSettings = observeVaultSettings,
scope = scope
)
@JvmStatic
@Provides
@Singleton
fun provideFieldsProvider(
dateProvider: DateProvider,
logger: Logger
): FieldParser = FieldParserImpl(dateProvider, logger)
@Module
interface Bindings {
@ -97,6 +114,6 @@ object UtilModule {
@Binds
@Singleton
fun bindDateTypeNameProvider(provider: DefaultDateTypeNameProvider) : DateTypeNameProvider
fun bindDateTypeNameProvider(provider: DefaultDateTypeNameProvider): DateTypeNameProvider
}
}

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.presentation.navigation.AppNavigation
import com.anytypeio.anytype.presentation.widgets.collection.Subscription
import com.anytypeio.anytype.ui.allcontent.AllContentFragment
import com.anytypeio.anytype.ui.auth.account.DeletedAccountFragment
import com.anytypeio.anytype.ui.date.DateObjectFragment
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.editor.EditorModalFragment
import com.anytypeio.anytype.ui.relations.RelationCreateFromScratchForObjectFragment
@ -318,4 +319,16 @@ class Navigator : AppNavigation {
)
)
}
override fun openDateObject(
objectId: Id,
space: Id
) {
navController?.navigate(
resId = R.id.dateObjectScreen,
args = DateObjectFragment.args(
objectId = objectId,
space = space)
)
}
}

View file

@ -259,6 +259,16 @@ class AllContentFragment : BaseComposeFragment(), ObjectTypeSelectionListener {
Timber.e(it, "Failed to open relation editing screen from all content")
}
}
is AllContentViewModel.Command.NavigateToDateObject -> {
runCatching {
navigation().openDateObject(
objectId = command.objectId,
space = command.space
)
}.onFailure { e ->
Timber.e(e, "Error while opening date object from All Objects screen")
}
}
}
}
}

View file

@ -55,6 +55,10 @@ class NavigationRouter(
typeId = command.typeId
)
is AppNavigation.Command.MigrationErrorScreen -> navigation.migrationErrorScreen()
is AppNavigation.Command.OpenDateObject -> navigation.openDateObject(
objectId = command.objectId,
space = command.space
)
else -> Timber.d("Nav command ignored: $command")
}
} catch (e: Exception) {

View file

@ -0,0 +1,263 @@
package com.anytypeio.anytype.ui.date
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.material.MaterialTheme
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.fragment.compose.content
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.fragment.findNavController
import androidx.navigation.navOptions
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_ui.views.BaseAlertDialog
import com.anytypeio.anytype.core_utils.ext.argString
import com.anytypeio.anytype.core_utils.ext.subscribe
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseComposeFragment
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.feature_date.viewmodel.UiErrorState
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectViewModel
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectVMFactory
import com.anytypeio.anytype.feature_date.ui.DateMainScreen
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectCommand
import com.anytypeio.anytype.feature_date.viewmodel.DateObjectVmParams
import com.anytypeio.anytype.ui.base.navigation
import com.anytypeio.anytype.ui.objects.creation.ObjectTypeSelectionFragment
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectTypeSelectionListener
import com.anytypeio.anytype.ui.search.GlobalSearchFragment
import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi
import com.google.accompanist.navigation.material.rememberBottomSheetNavigator
import javax.inject.Inject
import timber.log.Timber
class DateObjectFragment : BaseComposeFragment(), ObjectTypeSelectionListener {
@Inject
lateinit var factory: DateObjectVMFactory
private val vm by viewModels<DateObjectViewModel> { factory }
private lateinit var navComposeController: NavHostController
private val space get() = argString(ARG_SPACE)
private val objectId get() = argString(ARG_OBJECT_ID)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
) = content {
MaterialTheme {
DateLayoutScreenWrapper()
ErrorScreen()
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
subscribe(vm.effects) { effect ->
Timber.d("Received date effect: $effect")
when (effect) {
DateObjectCommand.Back -> {
runCatching {
findNavController().popBackStack()
}.onFailure { e ->
Timber.e(e, "Error while exiting back from all content")
}
}
DateObjectCommand.ExitToVault -> {
runCatching {
findNavController().navigate(R.id.actionOpenVault)
}.onFailure { e ->
Timber.e(e, "Error while exiting to vault from all content")
}
}
is DateObjectCommand.NavigateToEditor -> {
runCatching {
navigation().openDocument(
target = effect.id,
space = effect.space.id
)
}.onFailure {
toast("Failed to open document")
Timber.e(it, "Failed to open document from all content")
}
}
is DateObjectCommand.NavigateToSetOrCollection -> {
runCatching {
navigation().openObjectSet(
target = effect.id,
space = effect.space.id
)
}.onFailure {
toast("Failed to open object set")
Timber.e(it, "Failed to open object set from all content")
}
}
is DateObjectCommand.OpenChat -> {
runCatching {
navigation().openChat(
target = effect.target,
space = effect.space.id
)
}.onFailure {
Timber.e(it, "Failed to open a chat from all content")
}
}
DateObjectCommand.OpenGlobalSearch -> {
runCatching {
findNavController().navigate(
resId = R.id.globalSearchScreen,
args = GlobalSearchFragment.args(
space = space
)
)
}.onFailure { e ->
Timber.e(e, "Error while opening global search screen from all content")
}
}
is DateObjectCommand.NavigateToDateObject -> {
runCatching {
findNavController().navigate(
resId = R.id.dateObjectScreen,
args = args(
objectId = effect.objectId,
space = effect.space.id
),
navOptions = navOptions {
launchSingleTop = true
}
)
}.onFailure {
Timber.e(it, "Failed to navigate to date object")
}
}
DateObjectCommand.ExitToSpaceWidgets -> {
runCatching {
findNavController().navigate(R.id.actionExitToSpaceWidgets)
}.onFailure {
Timber.e(it, "Error while opening space switcher from all-content screen")
}
}
is DateObjectCommand.SendToast.UnexpectedLayout -> {
toast("Unexpected layout")
}
DateObjectCommand.TypeSelectionScreen -> {
val dialog = ObjectTypeSelectionFragment.new(space = space)
dialog.show(childFragmentManager, null)
}
}
}
}
override fun onSelectObjectType(objType: ObjectWrapper.Type) {
vm.onCreateObjectOfTypeClicked(objType = objType)
}
override fun onStart() {
super.onStart()
vm.onStart()
}
override fun onStop() {
super.onStop()
vm.onStop()
}
@OptIn(ExperimentalMaterialNavigationApi::class)
@Composable
fun DateLayoutScreenWrapper() {
val bottomSheetNavigator = rememberBottomSheetNavigator()
navComposeController = rememberNavController(bottomSheetNavigator)
NavHost(
navController = navComposeController,
startDestination = DATE_MAIN
) {
composable(route = DATE_MAIN) {
DateMainScreen(
uiCalendarIconState = vm.uiCalendarIconState.collectAsStateWithLifecycle().value,
uiSyncStatusBadgeState = vm.uiSyncStatusBadgeState.collectAsStateWithLifecycle().value,
uiHeaderState = vm.uiHeaderState.collectAsStateWithLifecycle().value,
uiFieldsState = vm.uiFieldsState.collectAsStateWithLifecycle().value,
uiObjectsListState = vm.uiObjectsListState.collectAsStateWithLifecycle().value,
uiNavigationWidget = vm.uiNavigationWidget.collectAsStateWithLifecycle().value,
uiFieldsSheetState = vm.uiFieldsSheetState.collectAsStateWithLifecycle().value,
uiContentState = vm.uiContentState.collectAsStateWithLifecycle().value,
canPaginate = vm.canPaginate.collectAsStateWithLifecycle().value,
uiCalendarState = vm.uiCalendarState.collectAsStateWithLifecycle().value,
uiSyncStatusState = vm.uiSyncStatusWidgetState.collectAsStateWithLifecycle().value,
onDateEvent = vm::onDateEvent
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ErrorScreen() {
val errorStateScreen = vm.errorState.collectAsStateWithLifecycle()
when (val state = errorStateScreen.value) {
UiErrorState.Hidden -> {
// Do nothing
}
is UiErrorState.Show -> {
val message = when (val r = state.reason) {
is UiErrorState.Reason.YearOutOfRange ->
stringResource(
id = R.string.date_layout_alert_date_out_of_range,
r.min,
r.max
)
is UiErrorState.Reason.ErrorGettingFields -> r.msg
is UiErrorState.Reason.ErrorGettingObjects -> r.msg
is UiErrorState.Reason.Other -> r.msg
}
BaseAlertDialog(
dialogText = message,
buttonText = stringResource(id = R.string.membership_error_button_text_dismiss),
onButtonClick = vm::hideError,
onDismissRequest = vm::hideError
)
}
}
}
override fun injectDependencies() {
val params = DateObjectVmParams(
spaceId = SpaceId(space),
objectId = objectId
)
componentManager().dateObjectComponent.get(params).inject(this)
}
override fun releaseDependencies() {
componentManager().dateObjectComponent.release()
}
override fun onApplyWindowRootInsets(view: View) {
// Do nothing. TODO add ime padding.
}
companion object DateLayoutNavigation {
private const val DATE_MAIN = "date_main"
const val ARG_SPACE = "arg.date.object.space"
const val ARG_OBJECT_ID = "arg.date.object.object_id"
fun args(space: Id, objectId: Id) = bundleOf(
ARG_SPACE to space,
ARG_OBJECT_ID to objectId
)
}
}

View file

@ -60,6 +60,7 @@ import com.anytypeio.anytype.core_ui.extensions.color
import com.anytypeio.anytype.core_ui.extensions.cursorYBottomCoordinate
import com.anytypeio.anytype.core_ui.features.editor.BlockAdapter
import com.anytypeio.anytype.core_ui.features.editor.DragAndDropAdapterDelegate
import com.anytypeio.anytype.core_ui.features.editor.EditorDatePicker
import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.DefaultScrollAndMoveTargetDescriptor
import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.ScrollAndMoveStateListener
import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.ScrollAndMoveTargetHighlighter
@ -753,6 +754,16 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
}
}
binding.editorDatePicker.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
EditorDatePicker(
uiState = vm.mentionDatePicker.collectAsStateWithLifecycle().value,
onEvent = vm::onEditorDatePickerEvent
)
}
}
BottomSheetBehavior.from(binding.styleToolbarMain).state = BottomSheetBehavior.STATE_HIDDEN
BottomSheetBehavior.from(binding.styleToolbarOther).state = BottomSheetBehavior.STATE_HIDDEN
BottomSheetBehavior.from(binding.styleToolbarColors).state =

View file

@ -520,6 +520,16 @@ class HomeScreenFragment : BaseComposeFragment(),
is Navigation.OpenSpaceSwitcher -> {
findNavController().navigate(R.id.actionOpenSpaceSwitcher)
}
is Navigation.OpenDateObject -> {
runCatching {
navigation().openDateObject(
objectId = destination.ctx,
space = destination.space
)
}.onFailure { e ->
Timber.e(e, "Error while opening date object from widgets")
}
}
}
}

View file

@ -16,6 +16,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.NavOptions
import androidx.navigation.NavOptions.*
import androidx.navigation.findNavController
import com.anytypeio.anytype.BuildConfig
import com.anytypeio.anytype.R
@ -34,7 +35,6 @@ import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.insets.EDGE_TO_EDGE_MIN_SDK
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.di.feature.discussions.DiscussionFragment
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.theme.GetTheme
import com.anytypeio.anytype.middleware.discovery.MDNSProvider
@ -50,6 +50,7 @@ import com.anytypeio.anytype.presentation.notifications.NotificationAction
import com.anytypeio.anytype.presentation.notifications.NotificationCommand
import com.anytypeio.anytype.presentation.wallpaper.WallpaperColor
import com.anytypeio.anytype.presentation.wallpaper.WallpaperView
import com.anytypeio.anytype.ui.date.DateObjectFragment
import com.anytypeio.anytype.ui.editor.CreateObjectFragment
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment
@ -232,6 +233,22 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
OpenObjectNavigation.NonValidObject -> {
toast(getString(R.string.error_non_valid_object))
}
is OpenObjectNavigation.OpenDataObject -> {
runCatching {
findNavController(R.id.fragment).navigate(
R.id.dateObjectScreen,
args = DateObjectFragment.args(
objectId = dest.target,
space = dest.space
),
navOptions = Builder()
.setPopUpTo(R.id.homeScreen, true)
.build()
)
}.onFailure {
Timber.e(it, "Error while date object navigation")
}
}
}
}
is Command.Deeplink.DeepLinkToObjectNotWorking -> {

View file

@ -104,6 +104,9 @@ class RemoteFilesManageFragment : BaseBottomSheetComposeFragment() {
is CollectionViewModel.Command.ExitToSpaceWidgets -> {
// Do nothing
}
is CollectionViewModel.Command.OpenDateObject -> {
// Do nothing
}
}
}

View file

@ -17,7 +17,6 @@ import androidx.navigation.fragment.findNavController
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.argStringList
import com.anytypeio.anytype.core_utils.ext.getFormattedDateTime
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
@ -25,7 +24,6 @@ import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
import com.anytypeio.anytype.presentation.sharing.AddToAnytypeViewModel
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.settings.typography
import java.util.Locale
import javax.inject.Inject
import kotlinx.coroutines.flow.map

View file

@ -30,7 +30,6 @@ import com.anytypeio.anytype.ui.gallery.GalleryInstallationFragment
import com.anytypeio.anytype.ui.home.HomeScreenFragment
import com.anytypeio.anytype.ui.multiplayer.RequestJoinSpaceFragment
import com.anytypeio.anytype.ui.payments.MembershipFragment
import com.anytypeio.anytype.ui.settings.ProfileSettingsFragment
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
import timber.log.Timber
@ -168,6 +167,17 @@ class VaultFragment : BaseComposeFragment() {
space = destination.space
)
}
is Navigation.OpenDateObject -> {
runCatching {
findNavController().navigate(R.id.actionOpenSpaceFromVault)
navigation().openDateObject(
objectId = destination.ctx,
space = destination.space
)
}.onFailure { e ->
Timber.e(e, "Error while opening date object from widgets")
}
}
}
}

View file

@ -28,6 +28,7 @@ import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.SetObjectListIsArchived
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.page.CreateObject
import com.anytypeio.anytype.domain.primitives.FieldParser
import com.anytypeio.anytype.domain.search.ObjectSearchSubscriptionContainer
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
import com.anytypeio.anytype.domain.templates.GetTemplates
@ -141,8 +142,7 @@ object CollectionModule {
fun getCreateObject(
repo: BlockRepository,
getDefaultObjectType: GetDefaultObjectType,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager
dispatchers: AppCoroutineDispatchers
): CreateObject = CreateObject(
repo = repo,
getDefaultObjectType = getDefaultObjectType,
@ -155,8 +155,7 @@ object CollectionModule {
fun provideGetDefaultPageType(
userSettingsRepository: UserSettingsRepository,
blockRepository: BlockRepository,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager,
dispatchers: AppCoroutineDispatchers
): GetDefaultObjectType = GetDefaultObjectType(
userSettingsRepository = userSettingsRepository,
blockRepository = blockRepository,
@ -209,4 +208,5 @@ interface CollectionDependencies : ComponentDependencies {
fun dateTypeNameProvider(): DateTypeNameProvider
fun analyticsHelperDelegate(): AnalyticSpaceHelperDelegate
fun provideUserPermissionProvider(): UserPermissionProvider
fun fieldParser(): FieldParser
}

View file

@ -121,6 +121,16 @@ class CollectionFragment : BaseComposeFragment(), ObjectTypeSelectionListener {
Timber.e(it, "Error while opening space switcher from full-screen widget")
}
}
is Command.OpenDateObject -> {
runCatching {
navigation().openDateObject(
objectId = command.target,
space = command.space
)
}.onFailure { e ->
Timber.e(e, "Error while opening date object from Collection screen")
}
}
}
}

View file

@ -51,13 +51,11 @@ import com.anytypeio.anytype.presentation.editor.cover.CoverGradient
import com.anytypeio.anytype.presentation.editor.cover.CoverView
import com.anytypeio.anytype.presentation.home.InteractionMode
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.objects.getProperName
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
import com.anytypeio.anytype.presentation.widgets.ViewId
import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetId
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.presentation.widgets.getWidgetObjectName
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenu
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
@ -104,13 +102,12 @@ fun DataViewListWidgetCard(
.padding(horizontal = 0.dp, vertical = 6.dp)
) {
WidgetHeader(
title = when (val source = item.source) {
is Widget.Source.Default -> {
source.obj.getWidgetObjectName() ?: stringResource(id = R.string.untitled)
title = when (val name = item.name) {
is WidgetView.Name.Default -> {
name.prettyPrintName ?: stringResource(id = R.string.untitled)
}
is Widget.Source.Bundled -> {
stringResource(id = source.res())
is WidgetView.Name.Bundled -> {
stringResource(id = name.source.res())
}
},
isCardMenuExpanded = isCardMenuExpanded,
@ -238,13 +235,12 @@ fun GalleryWidgetCard(
.padding(horizontal = 0.dp, vertical = 6.dp)
) {
WidgetHeader(
title = when (val source = item.source) {
is Widget.Source.Default -> {
source.obj.getWidgetObjectName() ?: stringResource(id = R.string.untitled)
title = when (val source = item.name) {
is WidgetView.Name.Default -> {
source.prettyPrintName ?: stringResource(id = R.string.untitled)
}
is Widget.Source.Bundled -> {
stringResource(id = source.res())
is WidgetView.Name.Bundled -> {
stringResource(id = source.source.res())
}
},
isCardMenuExpanded = isCardMenuExpanded,
@ -548,8 +544,14 @@ private fun GalleryWidgetItemCard(
.padding(start = 12.dp, top = 9.dp),
onTaskIconClicked = {}
)
val prettyPrintName = item.name.prettyPrintName
val name = if (prettyPrintName.isNullOrEmpty()) {
stringResource(id = R.string.untitled)
} else {
prettyPrintName
}
Text(
text = item.obj.getProperName().ifEmpty { stringResource(id = R.string.untitled) },
text = name,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = Caption1Medium,
@ -564,8 +566,14 @@ private fun GalleryWidgetItemCard(
)
}
} else {
val prettyPrintName = item.name.prettyPrintName
val name = if (prettyPrintName.isNullOrEmpty()) {
stringResource(id = R.string.untitled)
} else {
prettyPrintName
}
Text(
text = item.obj.getProperName().ifEmpty { stringResource(id = R.string.untitled) },
text = name,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
style = Caption1Medium,
@ -661,6 +669,9 @@ fun GalleryWidgetItemCardPreview() {
map = mapOf(
Relations.NAME to "Stephen Bann"
)
),
name = WidgetView.Name.Default(
prettyPrintName = "Stephen Bann"
)
),
onItemClicked = {}

View file

@ -33,7 +33,6 @@ import com.anytypeio.anytype.core_ui.views.HeadlineSubheading
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.presentation.widgets.getWidgetObjectName
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenu
@OptIn(ExperimentalFoundationApi::class)
@ -89,12 +88,13 @@ fun LinkWidgetCard(
.fillMaxWidth()
.height(40.dp)
) {
Text(
text = when (val source = item.source) {
is Widget.Source.Default -> {
source.obj.getWidgetObjectName() ?: stringResource(id = R.string.untitled)
text = when(val name = item.name) {
is WidgetView.Name.Bundled -> stringResource(id = name.source.res())
is WidgetView.Name.Default -> {
name.prettyPrintName ?: stringResource(id = R.string.untitled)
}
is Widget.Source.Bundled -> { stringResource(id = source.res()) }
},
maxLines = 1,
overflow = TextOverflow.Ellipsis,

View file

@ -33,7 +33,6 @@ import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetId
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.presentation.widgets.WidgetView.ListOfObjects.Type
import com.anytypeio.anytype.presentation.widgets.getWidgetObjectName
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenu
@Composable
@ -168,8 +167,7 @@ fun CompactListWidgetList(
}
)
Text(
text = element.obj.getWidgetObjectName()
?: stringResource(id = R.string.untitled),
text = element.name.prettyPrintName ?: stringResource(id = R.string.untitled),
modifier = Modifier
.padding(start = 8.dp)
.fillMaxWidth(),

View file

@ -55,7 +55,6 @@ import com.anytypeio.anytype.presentation.widgets.TreePath
import com.anytypeio.anytype.presentation.widgets.Widget
import com.anytypeio.anytype.presentation.widgets.WidgetId
import com.anytypeio.anytype.presentation.widgets.WidgetView
import com.anytypeio.anytype.presentation.widgets.getWidgetObjectName
import com.anytypeio.anytype.ui.widgets.menu.WidgetMenu
@Composable
@ -102,11 +101,11 @@ fun TreeWidgetCard(
)
) {
WidgetHeader(
title = when (val source = item.source) {
is Widget.Source.Default -> {
source.obj.getWidgetObjectName() ?: stringResource(id = R.string.untitled)
title = when (val name = item.name) {
is WidgetView.Name.Default -> {
name.prettyPrintName ?: stringResource(id = R.string.untitled)
}
is Widget.Source.Bundled -> { stringResource(id = source.res()) }
is WidgetView.Name.Bundled -> { stringResource(id = name.source.res()) }
},
isCardMenuExpanded = isCardMenuExpanded,
isHeaderMenuExpanded = isHeaderMenuExpanded,
@ -223,12 +222,12 @@ private fun TreeWidgetTreeItems(
icon = element.objectIcon,
modifier = Modifier.align(Alignment.CenterVertically).padding(start = 8.dp, end = 4.dp),
onTaskIconClicked = { isChecked ->
onObjectCheckboxClicked(element.obj.id, isChecked)
onObjectCheckboxClicked(element.id, isChecked)
}
)
}
Text(
text = element.obj.getWidgetObjectName() ?: stringResource(id = R.string.untitled),
text = element.name.prettyPrintName ?: stringResource(id = R.string.untitled),
modifier = Modifier
.padding(start = 8.dp)
.fillMaxWidth(),

View file

@ -317,4 +317,9 @@
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/editorDatePicker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal" />
</FrameLayout>

View file

@ -205,6 +205,16 @@
app:popUpToInclusive="false" />
</fragment>
<fragment
android:id="@+id/dateObjectScreen"
android:name="com.anytypeio.anytype.ui.date.DateObjectFragment"
android:label="Date Object"> {
<action
android:id="@+id/actionExitToSpaceWidgets"
app:popUpTo="@+id/homeScreen"
app:popUpToInclusive="false" />
</fragment>
<dialog
android:id="@+id/selectWidgetSourceScreen"
android:name="com.anytypeio.anytype.ui.widgets.SelectWidgetSourceFragment" />

View file

@ -31,7 +31,6 @@ data class Block(
val featuredRelations: List<String>? by default
val name: String? by default
val iconEmoji: String? by default
val iconOption: Double? by default
val coverId: Id? by default
val coverType: Double? by default
val iconImage: Id? get() = map.getSingleValue<Id>(Relations.ICON_IMAGE)
@ -42,7 +41,6 @@ data class Block(
val done: Boolean? by default
val lang: String? by default
val fileExt: String? by default
val fileMimeType: String? by default
val type: List<String>
get() = when (val value = map[TYPE_KEY]) {
is String -> listOf(value)
@ -60,10 +58,6 @@ data class Block(
else -> null
}
val analyticsContext: String? by default
val analyticsOriginalId: String? by default
companion object {
fun empty(): Fields = Fields(emptyMap())
const val NAME_KEY = "name"

View file

@ -480,6 +480,10 @@ sealed class Command {
data class DeleteRelationOptions(val optionIds: List<Id>)
data class RelationListWithValue(val space: SpaceId, val value: Any?)
data class ObjectDateByTimestamp(val space: SpaceId, val timestamp: Long)
data class SendJoinSpaceRequest(
val space: SpaceId,
val network: Id?,

View file

@ -1,5 +1,7 @@
package com.anytypeio.anytype.core_models
import java.text.DateFormat
const val NO_VALUE = ""
const val EMPTY_QUERY = ""
@ -16,4 +18,19 @@ const val DEFAULT_RELATIVE_DATES = true
/**
* The default value for showing the introduce vault.
*/
const val DEFAULT_SHOW_INTRODUCE_VAULT = true
const val DEFAULT_SHOW_INTRODUCE_VAULT = true
/**
* The default value for showing the time
*/
const val DEFAULT_TIME_STYLE = DateFormat.DEFAULT
/**
* The date range for the date picker.
*/
val DATE_PICKER_YEAR_RANGE = IntRange(0, 3000)
/**
* The maximum size of a snippet.
*/
const val MAX_SNIPPET_SIZE = 30

View file

@ -1,3 +1,10 @@
package com.anytypeio.anytype.core_models
import com.anytypeio.anytype.core_models.primitives.RelationKey
data class RelationLink(val key: Key, val format: RelationFormat)
data class RelationListWithValueItem(
val key: RelationKey,
val counter: Long
)

View file

@ -56,6 +56,8 @@ object Relations {
const val SYNC_DATE = "syncDate"
const val SYNC_STATUS = "syncStatus"
const val IS_HIDDEN_DISCOVERY = "isHiddenDiscovery"
const val MENTIONS = "mentions"
const val TIMESTAMP = "timestamp"
const val PAGE_COVER = "pageCover"

View file

@ -0,0 +1,8 @@
package com.anytypeio.anytype.core_models
sealed class RelativeDate {
data object Today : RelativeDate()
data object Tomorrow : RelativeDate()
data object Yesterday : RelativeDate()
data class Other(val formattedDate: String, val formattedTime: String) : RelativeDate()
}

View file

@ -1,6 +1,4 @@
package com.anytypeio.anytype.presentation.objects
import com.anytypeio.anytype.core_models.ObjectType
package com.anytypeio.anytype.core_models
object SupportedLayouts {
val layouts = listOf(
@ -56,16 +54,26 @@ object SupportedLayouts {
ObjectType.Layout.BOOKMARK
)
val dateLayouts = listOf(
ObjectType.Layout.DATE
)
val addAsLinkToLayouts = editorLayouts + listOf(
ObjectType.Layout.COLLECTION
)
val globalSearchLayouts = createObjectLayouts + fileLayouts
val globalSearchLayouts = createObjectLayouts + fileLayouts + dateLayouts
val widgetsLayouts = layouts + dateLayouts
fun isSupported(layout: ObjectType.Layout?) : Boolean {
return layouts.contains(layout)
}
fun isSupportedForWidgets(layout: ObjectType.Layout?) : Boolean {
return widgetsLayouts.contains(layout)
}
fun isEditorOrFileLayout(layout: ObjectType.Layout?) : Boolean {
return editorLayouts.contains(layout) || fileLayouts.contains(layout)
}

View file

@ -1,3 +0,0 @@
package com.anytypeio.anytype.core_models.exceptions
class SpaceLimitReachedException : Exception()

View file

@ -4,14 +4,14 @@ import com.anytypeio.anytype.core_models.Event
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.ObjectView
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.primitives.TimeInSeconds
import com.anytypeio.anytype.core_models.primitives.TimestampInSeconds
data class Version(
val id: Id,
val previousIds: List<Id>,
val spaceMember: Id,
val spaceMemberName: String,
val timestamp: TimeInSeconds,
val timestamp: TimestampInSeconds,
val groupId: Long
)

View file

@ -0,0 +1,23 @@
package com.anytypeio.anytype.core_models.primitives
import com.anytypeio.anytype.core_models.RelativeDate
sealed class Value<T> {
data class Single<T>(val single: T) : Value<T>()
data class Multiple<T>(val multiple: List<T>) : Value<T>()
}
sealed class Field<T>(open val value: Value<T>) {
data class Text(override val value: Value<String>) : Field<String>(value)
data class Date(override val value: Value.Single<FieldDateValue>) : Field<FieldDateValue>(value) {
val timestamp: TimestampInSeconds
get() = value.single.timestamp
val relativeDate: RelativeDate
get() = value.single.relativeDate
}
}
data class FieldDateValue(
val timestamp: TimestampInSeconds,
val relativeDate: RelativeDate
)

View file

@ -22,7 +22,7 @@ value class RelationId(val id: String)
value class RelationKey(val key: String)
@JvmInline
value class TimeInSeconds(val time: Long) {
value class TimestampInSeconds(val time: Long) {
val inMillis get() = time * 1000
}

View file

@ -8,12 +8,16 @@ import androidx.compose.ui.tooling.preview.Preview
backgroundColor = 0xFFFFFFFF,
showBackground = true,
uiMode = UI_MODE_NIGHT_NO,
name = "Light Mode"
name = "Light Mode",
apiLevel = 34,
showSystemUi = true
)
@Preview(
backgroundColor = 0x000000,
showBackground = true,
uiMode = UI_MODE_NIGHT_YES,
name = "Dark Mode"
name = "Dark Mode",
apiLevel = 34,
showSystemUi = true
)
annotation class DefaultPreviews

View file

@ -469,6 +469,29 @@ fun Editable.proceedWithSettingMentionSpan(
)
if (!mark.isArchived) setClickableSpan(click, mark)
}
is Markup.Mark.Mention.Date -> {
val placeholder =
ContextCompat.getDrawable(
context,
R.drawable.ic_obj_date_20
)
setSpan(
MentionSpan(
onImageResourceReady = onImageReady,
context = context,
imageSize = mentionImageSize,
imagePadding = mentionImagePadding,
param = mark.param,
placeholder = placeholder,
isArchived = false
),
mark.from,
mark.to,
Markup.MENTION_SPANNABLE_FLAG
)
setClickableSpan(click, mark)
}
}
}

View file

@ -0,0 +1,66 @@
package com.anytypeio.anytype.core_ui.common
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.res.colorResource
import com.anytypeio.anytype.core_ui.R
@Composable
fun ShimmerEffect(
modifier: Modifier,
widthOfShadowBrush: Int = 500,
angleOfAxisY: Float = 270f,
durationMillis: Int = 1000,
) {
val colorStart = colorResource(id = R.color.background_secondary)
val colorEnd = colorResource(id = R.color.shape_secondary)
val shimmerColors = listOf(
colorStart,
colorEnd,
colorStart
)
val infiniteTransition = rememberInfiniteTransition(label = "")
val translateAnimation = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = (durationMillis + widthOfShadowBrush).toFloat(),
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = durationMillis,
easing = LinearEasing,
),
repeatMode = RepeatMode.Restart,
),
label = "Shimmer loading animation",
)
val brush = Brush.linearGradient(
colors = shimmerColors,
start = Offset(x = translateAnimation.value - widthOfShadowBrush, y = 0.0f),
end = Offset(x = translateAnimation.value, y = angleOfAxisY),
)
Box(
modifier = modifier
) {
Spacer(
modifier = Modifier
.matchParentSize()
.background(brush)
)
}
}

View file

@ -1,6 +1,7 @@
package com.anytypeio.anytype.core_ui.extensions
import android.content.Context
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.webkit.MimeTypeMap
import androidx.annotation.ColorRes
@ -9,6 +10,7 @@ import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import com.anytypeio.anytype.core_models.DVSortType
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.RelativeDate
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_utils.const.MimeTypes
import com.anytypeio.anytype.presentation.objects.ObjectLayoutView
@ -291,4 +293,20 @@ fun RelationFormat.getPrettyName(): Int = when (this) {
RelationFormat.OBJECT -> R.string.relation_format_object
RelationFormat.RELATIONS -> R.string.relation_format_relation
RelationFormat.UNDEFINED -> R.string.undefined
}
fun RelativeDate.getPrettyName(
isTimeIncluded: Boolean = false,
resources: Resources
): String = when (this) {
is RelativeDate.Other -> {
if (isTimeIncluded) {
"$formattedDate $formattedTime"
} else {
formattedDate
}
}
is RelativeDate.Today -> resources.getString(R.string.today)
is RelativeDate.Tomorrow -> resources.getString(R.string.tomorrow)
is RelativeDate.Yesterday -> resources.getString(R.string.yesterday)
}

View file

@ -4,15 +4,16 @@ import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.presentation.sets.model.CellView
class DVGridCellDateHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bind(cell: CellView.Date) {
itemView.findViewById<TextView>(R.id.tvText).text = cell.timeInSecs?.formatTimestamp(
isMillis = false,
format = cell.dateFormat
val prettyDate = cell.relativeDate?.getPrettyName(
resources = itemView.resources,
isTimeIncluded = cell.isTimeIncluded
)
itemView.findViewById<TextView>(R.id.tvText).text = prettyDate
}
}

View file

@ -5,8 +5,8 @@ import android.widget.TextView
import com.anytypeio.anytype.core_models.DVFilterQuickOption
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemDvViewerFilterDateBinding
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.widgets.RelationFormatIconWidget
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.presentation.extension.hasValue
@ -44,7 +44,10 @@ class FilterDateViewHolder(val binding: ItemDvViewerFilterDateBinding) :
R.string.dates_days_from,
value
)
DVFilterQuickOption.EXACT_DATE -> item.filterValue.value?.formatTimestamp(isMillis = false)
DVFilterQuickOption.EXACT_DATE -> {
val relativeDate = item.relativeDate
relativeDate?.getPrettyName(resources = resources)
}
else -> item.quickOption.toName()
}
} else {

View file

@ -170,6 +170,7 @@ import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PICTURE_UPLOAD
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_PROFILE_TITLE
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_CHECKBOX
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_DATE
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_DEFAULT
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_DELETED
import com.anytypeio.anytype.presentation.editor.editor.model.types.Types.HOLDER_RELATION_FILE
@ -733,6 +734,10 @@ class BlockAdapter(
val binding = ItemBlockRelationDefaultBinding.inflate(inflater, parent, false)
RelationBlockViewHolder.Default(binding).setup(this)
}
HOLDER_RELATION_DATE -> {
val binding = ItemBlockRelationDefaultBinding.inflate(inflater, parent, false)
RelationBlockViewHolder.Date(binding).setup(this)
}
HOLDER_RELATION_PLACEHOLDER -> {
RelationBlockViewHolder.Placeholder(
ItemBlockRelationPlaceholderBinding.inflate(inflater, parent, false)
@ -1542,6 +1547,11 @@ class BlockAdapter(
holder.bind(item = item.view)
holder.bindHolder(item)
}
is RelationBlockViewHolder.Date -> {
val item = (blocks[position] as BlockView.Relation.Related)
holder.bind(item = item.view)
holder.bindHolder(item)
}
is RelationBlockViewHolder.Status -> {
val item = (blocks[position] as BlockView.Relation.Related)
holder.bind(item = item.view)

View file

@ -229,6 +229,13 @@ class BlockViewDiffUtil(
changes.add(RELATION_VALUE_CHANGED)
}
}
newRelationView is ObjectRelationView.Date && oldRelationView is ObjectRelationView.Date -> {
if (newRelationView.relativeDate != oldRelationView.relativeDate
|| newRelationView.isTimeIncluded != oldRelationView.isTimeIncluded) {
changes.add(RELATION_VALUE_CHANGED)
}
}
}
}

View file

@ -0,0 +1,62 @@
package com.anytypeio.anytype.core_ui.features.editor
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.relations.DatePickerContent
import com.anytypeio.anytype.presentation.editor.model.EditorDatePickerState
import com.anytypeio.anytype.presentation.editor.model.OnEditorDatePickerEvent
import com.anytypeio.anytype.presentation.sets.DateValueView
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditorDatePicker(
modifier: Modifier = Modifier,
uiState: EditorDatePickerState,
onEvent: (OnEditorDatePickerEvent) -> Unit
) {
if (uiState !is EditorDatePickerState.Visible) return
val bottomSheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true
)
val keyboardController = LocalSoftwareKeyboardController.current
LaunchedEffect(uiState) {
keyboardController?.hide()
}
ModalBottomSheet(
modifier = modifier,
dragHandle = null,
scrimColor = colorResource(id = R.color.modal_screen_outside_background),
containerColor = colorResource(id = R.color.background_secondary),
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp),
sheetState = bottomSheetState,
onDismissRequest = { onEvent(OnEditorDatePickerEvent.OnDatePickerDismiss) },
content = {
DatePickerContent(
state = DateValueView(timeInMillis = null),
showHeader = false,
onDateSelected = {
onEvent(
OnEditorDatePickerEvent.OnDateSelected(
timeInMillis = it
)
)
},
onTodayClicked = { onEvent(OnEditorDatePickerEvent.OnTodayClick) },
onTomorrowClicked = { onEvent(OnEditorDatePickerEvent.OnTomorrowClick) }
)
},
)
}

View file

@ -8,12 +8,14 @@ import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationCheckboxBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDateBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDefaultBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationFileBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationObjectBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationStatusBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationTagBinding
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.extensions.setBlockBackgroundColor
import com.anytypeio.anytype.core_ui.widgets.GridCellFileItem
import com.anytypeio.anytype.core_ui.widgets.RelationObjectItem
@ -61,6 +63,28 @@ sealed class ListRelationViewHolder(
}
}
class Date(binding: ItemRelationListRelationDateBinding) :
ListRelationViewHolder(binding.root) {
private val tvTitle = binding.content.tvRelationTitle
private val tvValue = binding.content.tvRelationValue
fun bind(item: ObjectRelationView) {
tvTitle.text = item.name
val item = item as? ObjectRelationView.Date ?: return
val relativeDate = item.relativeDate
if (relativeDate != null) {
tvValue.text = relativeDate.getPrettyName(
resources = itemView.resources
)
} else {
tvValue.text = null
tvValue.setHint(R.string.enter_date)
}
setLockIcon(tvTitle, item)
}
}
class Checkbox(binding: ItemRelationListRelationCheckboxBinding) :
ListRelationViewHolder(binding.root) {

View file

@ -30,6 +30,7 @@ import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.databinding.ItemBlockRelationDeletedBinding
import com.anytypeio.anytype.core_ui.extensions.clearDrawable
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.extensions.setDrawable
import com.anytypeio.anytype.core_ui.features.editor.BlockViewDiffUtil
import com.anytypeio.anytype.core_utils.ext.readableFileSize
@ -473,6 +474,42 @@ sealed class RelationBlockViewHolder(
}
}
class Date(binding: ItemBlockRelationDefaultBinding) :
RelationBlockViewHolder(binding.root) {
private val tvTitle = binding.tvRelationTitle
private val tvValue = binding.tvRelationValue
override val content = binding.content
override val selected = binding.selected
override val relationName: TextView = tvTitle
override val decoratableContainer: EditorDecorationContainer = binding.decorationContainer
fun bind(item: ObjectRelationView) {
applyRelationName(item.name, item.readOnly)
applyRelationValue(item)
}
override fun indentize(item: BlockView.Indentable) {
indent(item, itemView)
}
override fun applyDecorations(decorations: List<BlockView.Decoration>) {
super.applyContentDecorations(itemView, decorations)
}
override fun applyRelationValue(item: ObjectRelationView) {
val item = item as? ObjectRelationView.Date ?: return
val relativeDate = item.relativeDate
if (relativeDate != null) {
tvValue.text = relativeDate.getPrettyName(
resources = itemView.resources
)
} else {
tvValue.text = null
tvValue.setHint(R.string.enter_date)
}
}
}
private fun TextView.setReadOnly(isReadOnly: Boolean) {
if (isReadOnly) {

View file

@ -9,6 +9,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationCheckboxBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDateBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDefaultBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationFileBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationObjectBinding
@ -47,6 +48,18 @@ class SlashRelationsAdapter(
}
}
}
R.layout.item_relation_list_relation_date -> {
val binding =
ItemRelationListRelationDateBinding.inflate(inflater, parent, false)
ListRelationViewHolder.Date(binding).apply {
updateHeight(binding.root)
updatePadding(binding.root, defaultPadding)
binding.divider.visible()
itemView.setOnClickListener {
onItemClicked(bindingAdapterPosition)
}
}
}
R.layout.item_relation_list_relation_checkbox -> {
val binding =
ItemRelationListRelationCheckboxBinding.inflate(inflater, parent, false)
@ -196,6 +209,12 @@ class SlashRelationsAdapter(
check(view is ObjectRelationView.Default)
holder.bind(view)
}
is ListRelationViewHolder.Date -> {
check(item is SlashRelationView.Item)
val view = item.view
check(view is ObjectRelationView.Date)
holder.bind(view)
}
is RelationsSubheaderMenuHolder -> {
check(item is SlashRelationView.Section)
holder.bind(item)
@ -216,6 +235,7 @@ class SlashRelationsAdapter(
is ObjectRelationView.Status -> R.layout.item_relation_list_relation_status
is ObjectRelationView.Tags -> R.layout.item_relation_list_relation_tag
is ObjectRelationView.File -> R.layout.item_relation_list_relation_file
is ObjectRelationView.Date -> R.layout.item_relation_list_relation_date
else -> R.layout.item_relation_list_relation_default
}
}

View file

@ -44,7 +44,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_models.primitives.TimeInSeconds
import com.anytypeio.anytype.core_models.primitives.TimestampInSeconds
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.foundation.Dragger
import com.anytypeio.anytype.core_ui.foundation.Header
@ -367,7 +367,7 @@ private fun SpaceListScreenPreview() {
spaceMemberName = "John Doe",
icon = ObjectIcon.Profile.Avatar("A"),
spaceMember = "1",
timeStamp = TimeInSeconds(23423423L),
timeStamp = TimestampInSeconds(23423423L),
versions = emptyList(),
dateFormatted = "Today",
@ -378,7 +378,7 @@ private fun SpaceListScreenPreview() {
spaceMemberName = "Alice Doe",
icon = ObjectIcon.Profile.Avatar("B"),
spaceMember = "1",
timeStamp = TimeInSeconds(23423423L),
timeStamp = TimestampInSeconds(23423423L),
versions = emptyList(),
dateFormatted = "Today",
),
@ -388,7 +388,7 @@ private fun SpaceListScreenPreview() {
spaceMemberName = "Bob Doe",
icon = ObjectIcon.Profile.Avatar("C"),
spaceMember = "1",
timeStamp = TimeInSeconds(23423423L),
timeStamp = TimestampInSeconds(23423423L),
versions = emptyList(),
dateFormatted = "Today",
),

View file

@ -11,10 +11,13 @@ import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemListObjectBinding
import com.anytypeio.anytype.core_ui.databinding.ItemSearchNewObjectBinding
import com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
import com.anytypeio.anytype.core_utils.ext.gone
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_utils.ui.setOnThrottleClickListener
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.navigation.DefaultSearchItem
import com.anytypeio.anytype.presentation.navigation.NewObject
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.search.ObjectSearchSection
import com.anytypeio.anytype.presentation.widgets.source.BundledWidgetSourceView
@ -85,7 +88,7 @@ class DefaultObjectViewAdapter(
holder.title.setText(R.string.widget_source_anytype_library)
}
ObjectSearchSection.SelectWidgetSource.FromMyObjects -> {
holder.title.setText(R.string.objects)
holder.title.setText(R.string.your_objects)
}
ObjectSearchSection.SelectWidgetSource.DefaultLists -> {
holder.title.setText(R.string.widget_source_default_lists)
@ -129,9 +132,20 @@ class ObjectItemViewHolder(view: View) : ObjectViewHolder(view) {
fun bind(link: DefaultObjectView) {
title.text = link.name
subtitle.text = link.typeName
if (link.typeName != null) {
subtitle.visible()
subtitle.text = link.typeName
} else {
subtitle.gone()
}
icon.setIcon(link.icon)
}
fun bindSelectDateItem() {
title.setText(R.string.select_date)
subtitle.gone()
icon.setIcon(ObjectIcon.Empty.Date)
}
}
private fun inflate(
@ -168,7 +182,7 @@ class BundledWidgetSourceHolder(
BundledWidgetSourceView.Favorites -> {
with(binding) {
tvTitle.setText(R.string.favorites)
tvSubtitle.text = ""
tvSubtitle.gone()
ivIcon.setImageDrawable(
drawable = binding.root.context.resources.getDrawable(
R.drawable.ic_widget_bundled_source_favorites,
@ -181,6 +195,7 @@ class BundledWidgetSourceHolder(
BundledWidgetSourceView.Recent -> {
with(binding) {
tvTitle.setText(R.string.recent)
tvSubtitle.gone()
ivIcon.setImageDrawable(
drawable = binding.root.context.resources.getDrawable(
R.drawable.ic_widget_bundled_source_recently_edited,
@ -193,6 +208,7 @@ class BundledWidgetSourceHolder(
BundledWidgetSourceView.RecentLocal -> {
with(binding) {
tvTitle.setText(R.string.recently_opened)
tvSubtitle.visible()
tvSubtitle.setText(R.string.on_this_device)
ivIcon.setImageDrawable(
drawable = binding.root.context.resources.getDrawable(
@ -206,7 +222,7 @@ class BundledWidgetSourceHolder(
BundledWidgetSourceView.Sets -> {
with(binding) {
tvTitle.setText(R.string.sets)
tvSubtitle.text = ""
tvSubtitle.gone()
ivIcon.setImageDrawable(
drawable = binding.root.context.resources.getDrawable(
R.drawable.ic_widget_bundled_source_sets,
@ -218,7 +234,7 @@ class BundledWidgetSourceHolder(
BundledWidgetSourceView.Collections -> {
with(binding) {
tvTitle.setText(R.string.collections)
tvSubtitle.text = ""
tvSubtitle.gone()
ivIcon.setImageDrawable(
drawable = binding.root.context.resources.getDrawable(
R.drawable.ic_widget_bundled_source_collection,

View file

@ -8,6 +8,7 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationCheckboxBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDateBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDefaultBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationFileBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationObjectBinding
@ -131,6 +132,22 @@ class DocumentRelationAdapter(
R.layout.item_relation_list_section -> {
SectionViewHolder(view = inflater.inflate(viewType, parent, false))
}
R.layout.item_relation_list_relation_date -> {
val binding =
ItemRelationListRelationDateBinding.inflate(inflater, parent, false)
ListRelationViewHolder.Date(binding = binding).apply {
binding.featuredRelationCheckbox.visible()
itemView.setOnClickListener {
relationClicked(bindingAdapterPosition)
}
binding.featuredRelationCheckbox.setOnClickListener {
checkboxClicked(bindingAdapterPosition)
}
binding.ivActionDelete.setOnClickListener {
deleteClicked(bindingAdapterPosition)
}
}
}
else -> throw IllegalStateException("Unexpected view type: $viewType")
}
}
@ -224,6 +241,12 @@ class DocumentRelationAdapter(
check(view is ObjectRelationView.Default)
holder.bind(view)
}
is ListRelationViewHolder.Date -> {
check(item is RelationListViewModel.Model.Item)
val view = item.view
check(view is ObjectRelationView.Date)
holder.bind(view)
}
is SectionViewHolder -> {
check(item is RelationListViewModel.Model.Section)
holder.bind(item)
@ -249,6 +272,7 @@ class DocumentRelationAdapter(
is ObjectRelationView.Status -> R.layout.item_relation_list_relation_status
is ObjectRelationView.Tags -> R.layout.item_relation_list_relation_tag
is ObjectRelationView.File -> R.layout.item_relation_list_relation_file
is ObjectRelationView.Date -> R.layout.item_relation_list_relation_date
else -> R.layout.item_relation_list_relation_default
}
}

View file

@ -13,8 +13,8 @@ import com.anytypeio.anytype.core_ui.databinding.ItemCreateFilterObjectBinding
import com.anytypeio.anytype.core_ui.databinding.ItemCreateFilterStatusBinding
import com.anytypeio.anytype.core_ui.databinding.ItemCreateFilterTagBinding
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.extensions.light
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_utils.ext.invisible
import com.anytypeio.anytype.core_utils.ext.setDrawableColor
import com.anytypeio.anytype.core_utils.ext.visible
@ -175,7 +175,9 @@ class CreateFilterAdapter(
when (item.type) {
DVFilterQuickOption.EXACT_DATE -> {
tvDate.visible()
tvDate.text = item.value.formatTimestamp(isMillis = false)
tvDate.text = item.relativeDate?.getPrettyName(
resources = itemView.resources
)
}
DVFilterQuickOption.DAYS_AGO, DVFilterQuickOption.DAYS_AHEAD -> {
tvDate.visible()

View file

@ -29,6 +29,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_models.DATE_PICKER_YEAR_RANGE
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.foundation.Divider
import com.anytypeio.anytype.core_ui.foundation.Dragger
@ -37,14 +38,13 @@ import com.anytypeio.anytype.core_ui.views.Title1
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.presentation.sets.DateValueView
val DATE_RANGE = IntRange(0, 3000)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DatePickerContent(
state: DateValueView,
showHeader: Boolean = true,
onDateSelected: (Long?) -> Unit,
onClear: () -> Unit,
onClear: () -> Unit = {},
onTodayClicked: () -> Unit,
onTomorrowClicked: () -> Unit
) {
@ -56,7 +56,7 @@ fun DatePickerContent(
return state.isEditable
}
},
yearRange = DATE_RANGE
yearRange = DATE_PICKER_YEAR_RANGE
)
val isFirstLoad = remember { mutableStateOf(true) }
@ -78,7 +78,11 @@ fun DatePickerContent(
shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp)
)
) {
Header(state = state, onClear = onClear)
CalendarDragger()
if (showHeader) {
Header(state = state, onClear = onClear)
}
val todayContentColor = if (state.isEditable) {
colorResource(id = R.color.glyph_accent)
@ -144,17 +148,18 @@ fun DatePickerContent(
}
@Composable
private fun Header(state: DateValueView, onClear: () -> Unit) {
// Dragger at the top, centered
private fun CalendarDragger(modifier: Modifier = Modifier) {
Box(
modifier = Modifier
modifier = modifier
.fillMaxWidth()
.padding(vertical = 6.dp)
) {
Dragger(modifier = Modifier.align(Alignment.Center))
}
}
@Composable
private fun Header(state: DateValueView, onClear: () -> Unit) {
// Main content box
Box(
modifier = Modifier

View file

@ -0,0 +1,167 @@
package com.anytypeio.anytype.core_ui.syncstatus
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncAndP2PStatusState
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncError
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncStatus
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncUpdate
import com.anytypeio.anytype.core_ui.R
import androidx.compose.runtime.getValue
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.colorResource
import com.anytypeio.anytype.core_models.multiplayer.P2PStatusUpdate
import com.anytypeio.anytype.core_models.multiplayer.SpaceSyncNetwork
import com.anytypeio.anytype.core_ui.common.DefaultPreviews
@Composable
fun StatusBadge(
status: SpaceSyncAndP2PStatusState?,
modifier: Modifier = Modifier.size(20.dp)
) {
when (status) {
is SpaceSyncAndP2PStatusState.Error -> {
Image(
painter = painterResource(R.drawable.ic_sync_error_10),
contentDescription = null,
modifier = modifier
)
}
SpaceSyncAndP2PStatusState.Init -> {}
is SpaceSyncAndP2PStatusState.Success -> {
when (val spaceSyncUpdate = status.spaceSyncUpdate) {
SpaceSyncUpdate.Initial -> {}
is SpaceSyncUpdate.Update -> {
if (spaceSyncUpdate.error != SpaceSyncError.NULL) {
Image(
painter = painterResource(R.drawable.ic_sync_error_10),
contentDescription = null,
modifier = modifier
)
} else {
when (spaceSyncUpdate.status) {
SpaceSyncStatus.SYNCED -> {
Image(
painter = painterResource(R.drawable.ic_synced_10),
contentDescription = "Synced",
modifier = modifier.size(8.dp),
contentScale = ContentScale.Inside
)
}
SpaceSyncStatus.SYNCING -> {
PulsatingCircle(
color = colorResource(R.color.palette_system_green), // Replace with your color resource
modifier = modifier.size(24.dp)
)
}
SpaceSyncStatus.ERROR -> {
Image(
painter = painterResource(R.drawable.ic_sync_error_10),
contentDescription = "Sync Error",
modifier = modifier
)
}
SpaceSyncStatus.OFFLINE -> {
Image(
painter = painterResource(R.drawable.ic_sync_grey_10),
contentDescription = "Offline",
modifier = modifier
)
}
SpaceSyncStatus.NETWORK_UPDATE_NEEDED -> {
Image(
painter = painterResource(R.drawable.ic_sync_slow_10),
contentDescription = "Network Update Needed",
modifier = modifier
)
}
}
}
}
}
}
null -> {}
}
}
@Composable
fun PulsatingCircle(
color: Color,
modifier: Modifier = Modifier.size(20.dp)
) {
val infiniteTransition = rememberInfiniteTransition(label = "sync dot animation")
val scale by infiniteTransition.animateFloat(
initialValue = 0.0f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = tween(600, easing = FastOutSlowInEasing),
repeatMode = RepeatMode.Reverse
), label = "sync dot animation"
)
val density = LocalDensity.current
val centerRadius = with(density) { 4.dp.toPx() }
// Outer circles' base radii
val middleRadius = centerRadius + with(density) { 3.dp.toPx() } // 7 dp radius
val outerRadius = centerRadius + with(density) { 6.dp.toPx() } // 10 dp radius
Canvas(modifier = modifier) {
// Apply scaling to the outer circles
drawCircle(
color = color.copy(alpha = 0.2f),
radius = outerRadius * scale,
center = center
)
drawCircle(
color = color.copy(alpha = 0.4f),
radius = middleRadius * scale,
center = center
)
// Static center circle
drawCircle(
color = color,
radius = centerRadius,
center = center
)
}
}
@DefaultPreviews
@Composable
fun StatusBadgePreview() {
StatusBadge(
status = SpaceSyncAndP2PStatusState.Success(
spaceSyncUpdate = SpaceSyncUpdate.Update(
id = "1",
status = SpaceSyncStatus.SYNCED,
network = SpaceSyncNetwork.ANYTYPE,
error = SpaceSyncError.NULL,
syncingObjectsCounter = 2
),
p2PStatusUpdate = P2PStatusUpdate.Initial
)
)
}

View file

@ -201,5 +201,6 @@ fun imageAsset(emptyType: ObjectIcon.Empty): Int {
ObjectIcon.Empty.List -> R.drawable.ic_empty_state_list
ObjectIcon.Empty.ObjectType -> R.drawable.ic_empty_state_type
ObjectIcon.Empty.Page -> R.drawable.ic_empty_state_page
ObjectIcon.Empty.Date -> R.drawable.ic_obj_date_24
}
}

View file

@ -31,7 +31,7 @@ class ObjectIconWidget @JvmOverloads constructor(
) : FrameLayout(context, attrs, defStyleAttr) {
companion object {
const val DEFAULT_SIZE = 24
const val DEFAULT_SIZE = 28
}
val binding = WidgetObjectIconBinding.inflate(
@ -362,12 +362,13 @@ class ObjectIconWidget @JvmOverloads constructor(
}
private fun ObjectIcon.Empty.setEmptyIcon() {
val drawable = when (this) {
ObjectIcon.Empty.Bookmark -> R.drawable.ic_empty_state_link
ObjectIcon.Empty.Discussion -> R.drawable.ic_empty_state_chat
ObjectIcon.Empty.List -> R.drawable.ic_empty_state_list
ObjectIcon.Empty.ObjectType -> R.drawable.ic_empty_state_type
ObjectIcon.Empty.Page -> R.drawable.ic_empty_state_page
val (drawable, containerBackground) = when (this) {
ObjectIcon.Empty.Bookmark -> R.drawable.ic_empty_state_link to true
ObjectIcon.Empty.Discussion -> R.drawable.ic_empty_state_chat to true
ObjectIcon.Empty.List -> R.drawable.ic_empty_state_list to true
ObjectIcon.Empty.ObjectType -> R.drawable.ic_empty_state_type to true
ObjectIcon.Empty.Page -> R.drawable.ic_empty_state_page to true
ObjectIcon.Empty.Date -> R.drawable.ic_obj_date_24 to false
}
val icon = context.drawable(drawable)
with(binding) {
@ -377,7 +378,12 @@ class ObjectIconWidget @JvmOverloads constructor(
ivImage.invisible()
ivBookmark.setImageDrawable(null)
ivBookmark.gone()
emojiContainer.visible()
if (containerBackground) {
emojiContainer.visible()
} else {
emojiContainer.visible()
emojiContainer.setBackgroundResource(0)
}
}
}

View file

@ -11,6 +11,7 @@ import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.RelationValueListBinding
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.extensions.light
import com.anytypeio.anytype.core_utils.ext.gone
import com.anytypeio.anytype.core_utils.ext.setDrawableColor
@ -64,6 +65,7 @@ class RelationValueListWidget @JvmOverloads constructor(
is ObjectRelationView.ObjectType -> setObjectTypeRelation(relation)
is ObjectRelationView.Links -> setLinksRelation(relation)
is ObjectRelationView.Source -> setSourceRelation(relation, clickListener)
is ObjectRelationView.Date -> setDateRelation(relation)
}
if (!isLast) dot.visible()
}
@ -83,6 +85,26 @@ class RelationValueListWidget @JvmOverloads constructor(
}
//endregion
//region DATE
private fun setDateRelation(relation: ObjectRelationView.Date) {
val relativeDate = relation.relativeDate
if (relativeDate != null) {
val formattedDate = relativeDate.getPrettyName(
resources = resources
)
setupSingleTextItem(
name = formattedDate,
textColor = textColorPrimary
)
} else {
setupSingleTextItem(
name = relation.name,
textColor =textColorSecondary
)
}
}
//endregion
//region OBJECTS
private fun setObjectRelation(relation: ObjectRelationView.Object) {
when {

View file

@ -17,8 +17,8 @@ import androidx.core.view.updateLayoutParams
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.extensions.light
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.core_utils.ext.setDrawableColor
import com.anytypeio.anytype.emojifier.Emojifier
import com.anytypeio.anytype.presentation.objects.ObjectIcon
@ -158,9 +158,9 @@ class GalleryViewContentWidget @JvmOverloads constructor(
isSingleLine = true
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
text = relation.timeInMillis?.formatTimestamp(
isMillis = true,
format = relation.dateFormat
text = relation.relativeDate?.getPrettyName(
isTimeIncluded = relation.isTimeIncluded,
resources = resources
)
}
addView(view)

View file

@ -10,10 +10,10 @@ import androidx.constraintlayout.widget.ConstraintLayout
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.extensions.dark
import com.anytypeio.anytype.core_ui.extensions.getPrettyName
import com.anytypeio.anytype.core_ui.widgets.ListViewRelationObjectValueView
import com.anytypeio.anytype.core_ui.widgets.ListViewRelationTagValueView
import com.anytypeio.anytype.core_utils.ext.dimen
import com.anytypeio.anytype.core_utils.ext.formatTimestamp
import com.anytypeio.anytype.presentation.objects.ObjectIcon
import com.anytypeio.anytype.presentation.relations.model.DefaultObjectRelationValueView
import com.anytypeio.anytype.presentation.sets.model.ObjectView
@ -60,9 +60,9 @@ class ListViewItemRelationGroupWidget @JvmOverloads constructor(
ids.add(view.id)
}
is DefaultObjectRelationValueView.Date -> {
val value = relation.timeInMillis?.formatTimestamp(
isMillis = true,
format = relation.dateFormat
val value = relation.relativeDate?.getPrettyName(
isTimeIncluded = relation.isTimeIncluded,
resources = resources
)
if (value != null) {
val view = createView(value = value)

View file

@ -8,7 +8,7 @@ import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.WidgetMentionMenuBinding
import com.anytypeio.anytype.core_ui.widgets.toolbar.adapter.MentionAdapter
import com.anytypeio.anytype.core_utils.ui.NpaLinearLayoutManager
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.navigation.DefaultSearchItem
class MentionToolbar @JvmOverloads constructor(
context: Context,
@ -16,11 +16,10 @@ class MentionToolbar @JvmOverloads constructor(
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
private var mentionClick: ((DefaultObjectView, String, Int) -> Unit)? = null
private var mentionClick: ((DefaultSearchItem, String, Int) -> Unit)? = null
private var newPageClick: ((String) -> Unit)? = null
private val mentionAdapter by lazy {
MentionAdapter(
data = arrayListOf(),
onClicked = { objectView, filter, pos ->
mentionClick?.invoke(objectView, filter, pos)
},
@ -39,7 +38,7 @@ class MentionToolbar @JvmOverloads constructor(
}
fun setupClicks(
mentionClick: (DefaultObjectView, String, Int) -> Unit,
mentionClick: (DefaultSearchItem, String, Int) -> Unit,
newPageClick: (String) -> Unit
) {
this.mentionClick = mentionClick
@ -54,8 +53,13 @@ class MentionToolbar @JvmOverloads constructor(
}
}
fun addItems(items: List<DefaultObjectView>) {
mentionAdapter.setData(items)
fun addItems(items: List<DefaultSearchItem>) {
mentionAdapter.submitList(items)
if (items.isNotEmpty()) {
handler.post {
binding.recyclerView.scrollToPosition(0)
}
}
}
fun updateFilter(filter: String) {

View file

@ -2,43 +2,40 @@ package com.anytypeio.anytype.core_ui.widgets.toolbar.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemMentionNewPageBinding
import com.anytypeio.anytype.core_ui.databinding.ItemMentionSectionDateBinding
import com.anytypeio.anytype.core_ui.databinding.ItemMentionSectionObjectsBinding
import com.anytypeio.anytype.core_ui.features.navigation.DefaultObjectViewAdapter.Differ
import com.anytypeio.anytype.core_ui.features.navigation.DefaultObjectViewAdapter.ObjectItemViewHolder
import com.anytypeio.anytype.core_ui.features.navigation.DefaultObjectViewAdapter.ObjectViewHolder
import com.anytypeio.anytype.presentation.editor.editor.mention.MentionConst.MENTION_PREFIX
import com.anytypeio.anytype.presentation.navigation.DefaultObjectView
import com.anytypeio.anytype.presentation.navigation.DefaultSearchItem
import com.anytypeio.anytype.presentation.navigation.NewObject
import com.anytypeio.anytype.presentation.navigation.SectionDates
import com.anytypeio.anytype.presentation.navigation.SectionObjects
import com.anytypeio.anytype.presentation.navigation.SelectDateItem
class MentionAdapter(
private var data: ArrayList<DefaultObjectView>,
private var mentionFilter: String = "",
private val onClicked: (DefaultObjectView, String, Int) -> Unit,
private val newClicked: (String) -> Unit
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
fun setData(mentions: List<DefaultObjectView>) {
if (mentions.isEmpty()) {
data.clear()
notifyDataSetChanged()
} else {
data.clear()
data.addAll(mentions)
notifyDataSetChanged()
}
}
private val onClicked: (DefaultSearchItem, String, Int) -> Unit,
private val newClicked: (String) -> Unit,
private val onCurrentListChanged: (Int, Int) -> Unit = { prevSize, newSize -> },
) : ListAdapter<DefaultSearchItem, ObjectViewHolder>(Differ) {
fun updateFilter(filter: String) {
mentionFilter = filter
}
fun clear() {
submitList(emptyList())
mentionFilter = ""
val size = data.size
data.clear()
notifyItemRangeRemoved(0, size + 1)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ObjectViewHolder {
val inflater = LayoutInflater.from(parent.context)
return when (viewType) {
TYPE_NEW_PAGE -> NewPageViewHolder(
@ -48,38 +45,59 @@ class MentionAdapter(
newClicked(mentionFilter)
}
}
TYPE_MENTION ->
TYPE_MENTION, TYPE_SELECT_DATE ->
ObjectItemViewHolder(
view = inflater.inflate(R.layout.item_list_object_small, parent, false)
).apply {
itemView.setOnClickListener {
val pos = bindingAdapterPosition
if (pos != RecyclerView.NO_POSITION) {
onClicked(data[pos], mentionFilter, pos)
val item = getItem(pos)
onClicked(item, mentionFilter, pos)
}
}
}
TYPE_SECTION_DATES -> SectionDatesViewHolder(
binding = ItemMentionSectionDateBinding.inflate(inflater, parent, false)
)
TYPE_SECTION_OBJECTS -> SectionObjectsViewHolder(
binding = ItemMentionSectionObjectsBinding.inflate(inflater, parent, false)
)
else -> throw IllegalStateException("Unexpected view type: $viewType")
}
}
override fun getItemCount(): Int = data.size + 1
override fun getItemViewType(position: Int): Int {
return if (position > data.lastIndex) TYPE_NEW_PAGE else TYPE_MENTION
override fun onCurrentListChanged(
previousList: MutableList<DefaultSearchItem>,
currentList: MutableList<DefaultSearchItem>
) {
super.onCurrentListChanged(previousList, currentList)
onCurrentListChanged(previousList.size, currentList.size)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
if (holder is ObjectItemViewHolder) {
holder.bind(data[position])
override fun getItemViewType(position: Int): Int = when (val item = getItem(position)) {
is DefaultObjectView -> TYPE_MENTION
is SectionDates -> TYPE_SECTION_DATES
is SectionObjects -> TYPE_SECTION_OBJECTS
is NewObject -> TYPE_NEW_PAGE
is SelectDateItem -> TYPE_SELECT_DATE
else -> throw IllegalStateException("Unexpected item type: ${item.javaClass.name}")
}
override fun onBindViewHolder(holder: ObjectViewHolder, position: Int) {
val item = getItem(position)
if (holder is ObjectItemViewHolder && item is DefaultObjectView) {
holder.bind(item)
}
if (holder is NewPageViewHolder) {
holder.bind(filter = mentionFilter.removePrefix(MENTION_PREFIX))
}
if (holder is ObjectItemViewHolder && item is SelectDateItem) {
holder.bindSelectDateItem()
}
}
class NewPageViewHolder(binding: ItemMentionNewPageBinding) :
RecyclerView.ViewHolder(binding.root) {
ObjectViewHolder(binding.root) {
private val tvTitle = binding.text
@ -92,11 +110,19 @@ class MentionAdapter(
"${res.getString(R.string.mention_suggester_create_object)} \"$filter\""
}
}
}
class SectionDatesViewHolder(binding: ItemMentionSectionDateBinding) :
ObjectViewHolder(binding.root)
class SectionObjectsViewHolder(binding: ItemMentionSectionObjectsBinding) :
ObjectViewHolder(binding.root)
companion object {
const val TYPE_NEW_PAGE = 1
const val TYPE_MENTION = 2
const val TYPE_SECTION_DATES = 3
const val TYPE_SECTION_OBJECTS = 4
const val TYPE_SELECT_DATE = 5
}
}

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M3,5.999C3,5.585 3.335,5.25 3.749,5.25H20.251C20.665,5.25 21,5.585 21,5.999C21,6.413 20.665,6.748 20.251,6.748H3.749C3.335,6.748 3,6.413 3,5.999ZM3,17.999C3,17.585 3.335,17.25 3.749,17.25H20.251C20.665,17.25 21,17.585 21,17.999C21,18.413 20.665,18.748 20.251,18.748H3.749C3.335,18.748 3,18.413 3,17.999ZM3.749,11.25C3.335,11.25 3,11.585 3,11.999C3,12.413 3.335,12.748 3.749,12.748H20.251C20.665,12.748 21,12.413 21,11.999C21,11.585 20.665,11.25 20.251,11.25H3.749Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,31 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M14.5,11.25C14.5,11.112 14.612,11 14.75,11H17.25C17.388,11 17.5,11.112 17.5,11.25V12.25C17.5,12.388 17.388,12.5 17.25,12.5H14.75C14.612,12.5 14.5,12.388 14.5,12.25V11.25Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10.5,13.75C10.5,13.612 10.612,13.5 10.75,13.5H13.25C13.388,13.5 13.5,13.612 13.5,13.75V14.75C13.5,14.888 13.388,15 13.25,15H10.75C10.612,15 10.5,14.888 10.5,14.75V13.75Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M14.5,13.75C14.5,13.612 14.612,13.5 14.75,13.5H17.25C17.388,13.5 17.5,13.612 17.5,13.75V14.75C17.5,14.888 17.388,15 17.25,15H14.75C14.612,15 14.5,14.888 14.5,14.75V13.75Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10.5,11.25C10.5,11.112 10.612,11 10.75,11H13.25C13.388,11 13.5,11.112 13.5,11.25V12.25C13.5,12.388 13.388,12.5 13.25,12.5H10.75C10.612,12.5 10.5,12.388 10.5,12.25V11.25Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M6.5,13.75C6.5,13.612 6.612,13.5 6.75,13.5H9.25C9.388,13.5 9.5,13.612 9.5,13.75V14.75C9.5,14.888 9.388,15 9.25,15H6.75C6.612,15 6.5,14.888 6.5,14.75V13.75Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M10.5,16.25C10.5,16.112 10.612,16 10.75,16H13.25C13.388,16 13.5,16.112 13.5,16.25V17.25C13.5,17.388 13.388,17.5 13.25,17.5H10.75C10.612,17.5 10.5,17.388 10.5,17.25V16.25Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M6.5,16.25C6.5,16.112 6.612,16 6.75,16H9.25C9.388,16 9.5,16.112 9.5,16.25V17.25C9.5,17.388 9.388,17.5 9.25,17.5H6.75C6.612,17.5 6.5,17.388 6.5,17.25V16.25Z"
android:fillColor="@color/glyph_active"/>
<path
android:pathData="M4,9V17C4,18.381 5.119,19.5 6.5,19.5H17.5C18.881,19.5 20,18.381 20,17V9H4ZM2.5,7C2.5,4.791 4.291,3 6.5,3H17.5C19.709,3 21.5,4.791 21.5,7V17C21.5,19.209 19.709,21 17.5,21H6.5C4.291,21 2.5,19.209 2.5,17V7Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12.561,21C11.094,21 9.797,20.799 8.67,20.398C7.544,20.002 6.597,19.416 5.83,18.642C5.063,17.869 4.483,16.92 4.09,15.798C3.697,14.675 3.5,13.39 3.5,11.943C3.5,10.543 3.699,9.291 4.097,8.188C4.5,7.084 5.082,6.148 5.844,5.379C6.611,4.605 7.541,4.015 8.635,3.609C9.732,3.203 10.974,3 12.36,3C13.707,3 14.886,3.22 15.898,3.659C16.914,4.094 17.763,4.684 18.443,5.429C19.129,6.17 19.642,7.003 19.982,7.93C20.327,8.857 20.5,9.812 20.5,10.796C20.5,11.489 20.466,12.191 20.399,12.903C20.332,13.615 20.191,14.269 19.975,14.866C19.759,15.459 19.426,15.936 18.976,16.299C18.53,16.662 17.926,16.844 17.163,16.844C16.828,16.844 16.458,16.791 16.056,16.686C15.653,16.581 15.296,16.407 14.984,16.163C14.673,15.92 14.488,15.592 14.431,15.182H14.344C14.229,15.459 14.052,15.721 13.812,15.97C13.577,16.218 13.268,16.416 12.884,16.565C12.506,16.713 12.043,16.777 11.497,16.758C10.873,16.734 10.325,16.596 9.85,16.342C9.375,16.084 8.977,15.736 8.656,15.296C8.34,14.852 8.1,14.338 7.937,13.756C7.779,13.168 7.7,12.535 7.7,11.857C7.7,11.212 7.796,10.622 7.987,10.087C8.179,9.552 8.445,9.084 8.786,8.682C9.131,8.281 9.533,7.961 9.994,7.722C10.459,7.478 10.96,7.328 11.497,7.271C11.976,7.223 12.412,7.244 12.805,7.335C13.198,7.421 13.522,7.553 13.776,7.729C14.03,7.901 14.191,8.092 14.258,8.303H14.344V7.5H15.869V13.978C15.869,14.379 15.981,14.733 16.207,15.038C16.432,15.344 16.761,15.497 17.192,15.497C17.681,15.497 18.055,15.33 18.314,14.995C18.578,14.661 18.757,14.145 18.853,13.448C18.954,12.75 19.004,11.857 19.004,10.767C19.004,10.127 18.916,9.497 18.738,8.876C18.566,8.25 18.302,7.665 17.947,7.12C17.597,6.576 17.154,6.096 16.617,5.68C16.08,5.264 15.449,4.939 14.726,4.705C14.006,4.467 13.189,4.347 12.273,4.347C11.147,4.347 10.137,4.522 9.246,4.87C8.359,5.214 7.604,5.718 6.981,6.382C6.362,7.041 5.89,7.844 5.564,8.79C5.243,9.731 5.082,10.801 5.082,12C5.082,13.218 5.243,14.3 5.564,15.246C5.89,16.192 6.369,16.99 7.002,17.639C7.64,18.289 8.428,18.781 9.368,19.115C10.308,19.455 11.391,19.624 12.618,19.624C13.146,19.624 13.666,19.574 14.179,19.474C14.692,19.373 15.145,19.264 15.538,19.144C15.931,19.025 16.214,18.936 16.387,18.879L16.789,20.198C16.492,20.322 16.104,20.446 15.624,20.57C15.15,20.694 14.642,20.797 14.1,20.878C13.563,20.959 13.05,21 12.561,21ZM11.727,15.296C12.369,15.296 12.889,15.167 13.287,14.909C13.685,14.651 13.975,14.262 14.157,13.741C14.34,13.22 14.431,12.564 14.431,11.771C14.431,10.968 14.33,10.342 14.129,9.893C13.927,9.444 13.63,9.129 13.237,8.947C12.844,8.766 12.36,8.675 11.784,8.675C11.238,8.675 10.77,8.818 10.382,9.105C9.998,9.387 9.704,9.764 9.497,10.237C9.296,10.705 9.195,11.217 9.195,11.771C9.195,12.382 9.277,12.958 9.44,13.498C9.603,14.033 9.869,14.467 10.238,14.802C10.607,15.131 11.104,15.296 11.727,15.296Z"
android:fillColor="@color/glyph_active"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:pathData="M12.778,8.027C12.778,7.889 12.89,7.777 13.028,7.777H15.305C15.443,7.777 15.555,7.889 15.555,8.027V9.194C15.555,9.332 15.443,9.444 15.305,9.444H13.028C12.89,9.444 12.778,9.332 12.778,9.194V8.027ZM8.611,10.805C8.611,10.667 8.723,10.555 8.861,10.555H11.139C11.277,10.555 11.389,10.667 11.389,10.805V11.972C11.389,12.11 11.277,12.222 11.139,12.222H8.861C8.723,12.222 8.611,12.11 8.611,11.972V10.805ZM13.028,10.555C12.89,10.555 12.778,10.667 12.778,10.805V11.972C12.778,12.11 12.89,12.222 13.028,12.222H15.305C15.443,12.222 15.555,12.11 15.555,11.972V10.805C15.555,10.667 15.443,10.555 15.305,10.555H13.028ZM8.611,8.027C8.611,7.889 8.723,7.777 8.861,7.777H11.139C11.277,7.777 11.389,7.889 11.389,8.027V9.194C11.389,9.332 11.277,9.444 11.139,9.444H8.861C8.723,9.444 8.611,9.332 8.611,9.194V8.027ZM4.694,10.555C4.556,10.555 4.444,10.667 4.444,10.805V11.972C4.444,12.11 4.556,12.222 4.694,12.222H6.972C7.11,12.222 7.222,12.11 7.222,11.972V10.805C7.222,10.667 7.11,10.555 6.972,10.555H4.694ZM8.611,13.583C8.611,13.445 8.723,13.333 8.861,13.333H11.139C11.277,13.333 11.389,13.445 11.389,13.583V14.75C11.389,14.888 11.277,15 11.139,15H8.861C8.723,15 8.611,14.888 8.611,14.75V13.583ZM4.694,13.333C4.556,13.333 4.444,13.445 4.444,13.583V14.75C4.444,14.888 4.556,15 4.694,15H6.972C7.11,15 7.222,14.888 7.222,14.75V13.583C7.222,13.445 7.11,13.333 6.972,13.333H4.694Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
<path
android:pathData="M1.666,5.556C1.666,3.715 3.159,2.223 5,2.223H15C16.841,2.223 18.333,3.715 18.333,5.556V14.445C18.333,16.286 16.841,17.778 15,17.778H5C3.159,17.778 1.666,16.286 1.666,14.445V5.556ZM2.778,14.445V5.556L17.222,5.556V14.445C17.222,15.672 16.227,16.667 15,16.667H5C3.773,16.667 2.778,15.672 2.778,14.445Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
</vector>

View file

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M15.333,9.583C15.333,9.445 15.445,9.333 15.583,9.333H18.417C18.555,9.333 18.667,9.445 18.667,9.583V11.083C18.667,11.221 18.555,11.333 18.417,11.333H15.583C15.445,11.333 15.333,11.221 15.333,11.083V9.583ZM10.333,12.916C10.333,12.778 10.445,12.666 10.583,12.666H13.417C13.555,12.666 13.667,12.778 13.667,12.916V14.416C13.667,14.554 13.555,14.666 13.417,14.666H10.583C10.445,14.666 10.333,14.554 10.333,14.416V12.916ZM15.583,12.666C15.445,12.666 15.333,12.778 15.333,12.916V14.416C15.333,14.554 15.445,14.666 15.583,14.666H18.417C18.555,14.666 18.667,14.554 18.667,14.416V12.916C18.667,12.778 18.555,12.666 18.417,12.666H15.583ZM10.333,9.583C10.333,9.445 10.445,9.333 10.583,9.333H13.417C13.555,9.333 13.667,9.445 13.667,9.583V11.083C13.667,11.221 13.555,11.333 13.417,11.333H10.583C10.445,11.333 10.333,11.221 10.333,11.083V9.583ZM5.583,12.666C5.445,12.666 5.333,12.778 5.333,12.916V14.416C5.333,14.554 5.445,14.666 5.583,14.666H8.417C8.555,14.666 8.667,14.554 8.667,14.416V12.916C8.667,12.778 8.555,12.666 8.417,12.666H5.583ZM10.333,16.25C10.333,16.112 10.445,16 10.583,16H13.417C13.555,16 13.667,16.112 13.667,16.25V17.75C13.667,17.888 13.555,18 13.417,18H10.583C10.445,18 10.333,17.888 10.333,17.75V16.25ZM5.583,16C5.445,16 5.333,16.112 5.333,16.25V17.75C5.333,17.888 5.445,18 5.583,18H8.417C8.555,18 8.667,17.888 8.667,17.75V16.25C8.667,16.112 8.555,16 8.417,16H5.583Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
<path
android:pathData="M2,6.667C2,4.458 3.791,2.667 6,2.667H18C20.209,2.667 22,4.458 22,6.667V17.334C22,19.543 20.209,21.334 18,21.334H6C3.791,21.334 2,19.543 2,17.334V6.667ZM3.333,17.334V6.667L20.667,6.667V17.334C20.667,18.806 19.473,20 18,20H6C4.527,20 3.333,18.806 3.333,17.334Z"
android:fillColor="@color/glyph_active"
android:fillType="evenOdd"/>
</vector>

View file

@ -3,57 +3,61 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="@dimen/dp_72">
<com.anytypeio.anytype.core_ui.widgets.ObjectIconWidget
android:id="@+id/ivIcon"
android:layout_width="@dimen/list_item_object_icon_width"
android:layout_height="@dimen/list_item_object_icon_height"
android:layout_marginStart="@dimen/list_item_object_icon_margin_start"
android:layout_marginTop="@dimen/list_item_object_icon_margin_top"
android:layout_marginBottom="@dimen/list_item_object_icon_margin_bottom"
android:layout_gravity="center_vertical"
android:contentDescription="@string/content_desc_object_icon"
app:checkboxSize="@dimen/list_item_object_checkbox_size"
app:emojiSize="@dimen/list_item_object_emoji_size"
app:hasEmojiRounded8Background="true"
app:hasInitialRounded8Background="true"
app:emojiSize="@dimen/list_item_object_emoji_size"
app:imageSize="@dimen/list_item_object_icon_height"
app:imageCornerRadius="@dimen/list_item_object_image_corner_radius"
app:imageSize="@dimen/list_item_object_icon_height"
app:initialTextSize="@dimen/list_item_object_initials_size" />
<TextView
android:id="@+id/tvTitle"
style="@style/ObjectListItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_object_title_margin_start"
android:layout_marginTop="@dimen/list_item_object_title_margin_top"
android:layout_marginEnd="@dimen/list_item_object_title_margin_end"
android:hint="@string/untitled"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="end"
tools:text="Is your feature request related to a problem? Please describe." />
<TextView
android:id="@+id/tvSubtitle"
style="@style/ObjectListItemSubtitle"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_object_subtitle_margin_start"
android:layout_marginTop="@dimen/list_item_object_subtitle_margin_top"
android:layout_marginEnd="@dimen/list_item_object_subtitle_margin_end"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
tools:text="Task" />
android:orientation="vertical"
android:layout_gravity="center_vertical"
android:layout_marginStart="76dp"
android:layout_marginEnd="@dimen/dp_16">
<TextView
android:id="@+id/tvTitle"
style="@style/ObjectListItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:hint="@string/untitled"
android:maxLines="1"
android:singleLine="true"
tools:text="Is your feature request related to a problem? Please describe." />
<TextView
android:id="@+id/tvSubtitle"
style="@style/ObjectListItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
tools:text="Task"
tools:visibility="visible" />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_gravity="bottom"
android:layout_marginStart="@dimen/list_item_object_subtitle_margin_start"
android:layout_marginTop="68dp"
android:layout_marginEnd="@dimen/list_item_object_subtitle_margin_end"
android:background="@drawable/divider_relations"
android:visibility="gone"

View file

@ -21,32 +21,34 @@
app:imageCornerRadius="@dimen/list_item_object_image_corner_radius"
app:initialTextSize="@dimen/list_item_object_half_initials_size" />
<TextView
android:id="@+id/tvTitle"
style="@style/ObjectListItemTitle"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_object_half_title_margin_start"
android:layout_marginTop="@dimen/list_item_object_half_title_margin_top"
android:layout_marginEnd="@dimen/list_item_object_half_title_margin_end"
android:hint="@string/untitled"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="end"
tools:text="Is your feature request related to a problem? Please describe." />
android:layout_gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/tvSubtitle"
style="@style/ObjectListItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/list_item_object_half_subtitle_margin_start"
android:layout_marginTop="@dimen/list_item_object_half_subtitle_margin_top"
android:layout_marginEnd="@dimen/list_item_object_half_subtitle_margin_end"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
tools:text="Task" />
<TextView
android:id="@+id/tvTitle"
style="@style/ObjectListItemTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/untitled"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="end"
tools:text="Is your feature request related to a problem? Please describe." />
<TextView
android:id="@+id/tvSubtitle"
style="@style/ObjectListItemSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
tools:text="Task" />
</LinearLayout>
<View
android:id="@+id/view"

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/mention_section_item_height">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextView.ContentStyle.Relations.2"
android:textColor="@color/text_secondary"
android:ellipsize="end"
android:maxLines="1"
android:paddingBottom="4dp"
android:layout_gravity="start|bottom"
android:text="@string/mention_section_dates" />
</FrameLayout>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/mention_section_item_height">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextView.ContentStyle.Relations.2"
android:textColor="@color/text_secondary"
android:ellipsize="end"
android:maxLines="1"
android:paddingBottom="4dp"
android:layout_gravity="start|bottom"
android:text="@string/mention_section_objects" />
</FrameLayout>

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/itemContainer"
android:layout_width="match_parent"
android:layout_height="@dimen/object_settings_relations_item_height"
android:background="@drawable/default_ripple">
<ImageView
android:id="@+id/ivActionDelete"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:paddingEnd="@dimen/dp_10"
android:visibility="gone"
android:src="@drawable/ic_relation_delete"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<include
android:id="@+id/content"
layout="@layout/item_document_relation_default"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/featuredRelationCheckbox"
app:layout_constraintStart_toEndOf="@id/ivActionDelete"
app:layout_constraintTop_toTopOf="parent"
app:layout_goneMarginLeft="0dp" />
<ImageView
android:id="@+id/featuredRelationCheckbox"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical"
android:paddingStart="@dimen/dp_12"
android:src="@drawable/ic_featured_relation_checkbox"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<View
android:id="@+id/divider"
android:layout_width="0dp"
android:layout_height="0.5dp"
android:layout_gravity="bottom"
android:background="@color/shape_primary"
app:layout_constraintBottom_toBottomOf="@+id/content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/content" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -15,9 +15,8 @@
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="76dp"
android:fontFamily="@font/inter_medium"
style="@style/TextView.ContentStyle.PreviewTitles.2.Medium"
android:text="@string/new_object"
android:textColor="@color/text_primary"
android:textSize="15sp" />
android:textColor="@color/text_primary" />
</FrameLayout>

View file

@ -23,9 +23,9 @@
android:id="@+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="20dp"
android:layout_marginEnd="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View file

@ -52,7 +52,7 @@
<color name="text_button_label">#FFFFFF</color>
<color name="background_primary">#FFFFFF</color>
<color name="background_notification_primary">#000000</color>
<color name="background_notification_primary">#26000000</color>
<color name="background_secondary">#FFFFFF</color>
<color name="background_highlighted">#144F4F4F</color>
<color name="background_highlighted_light">#0A4F4F4F</color>
@ -304,4 +304,6 @@
<color name="navigation_panel">#99FFFFFF</color>
<color name="navigation_panel_icon">#66000000</color>
<color name="modal_screen_outside_background">#26000000</color>
</resources>

View file

@ -75,6 +75,7 @@
<dimen name="mention_span_initials_size_header_one">19sp</dimen>
<dimen name="mention_suggester_item_height">56dp</dimen>
<dimen name="mention_section_item_height">36dp</dimen>
<dimen name="mention_list_padding_top">4dp</dimen>
<dimen name="mention_list_padding_bottom">5dp</dimen>
<dimen name="mention_divider_height">1dp</dimen>
@ -104,17 +105,17 @@
<!-- Object items is full screen lists -->
<dimen name="list_item_object_icon_width">48dp</dimen>
<dimen name="list_item_object_icon_height">48dp</dimen>
<dimen name="list_item_object_icon_margin_start">20dp</dimen>
<dimen name="list_item_object_icon_margin_start">16dp</dimen>
<dimen name="list_item_object_icon_margin_top">10dp</dimen>
<dimen name="list_item_object_icon_margin_bottom">10dp</dimen>
<dimen name="list_item_object_title_margin_top">13dp</dimen>
<dimen name="list_item_object_title_margin_start">80dp</dimen>
<dimen name="list_item_object_title_margin_end">20dp</dimen>
<dimen name="list_item_object_subtitle_margin_top">34dp</dimen>
<dimen name="list_item_object_subtitle_margin_start">80dp</dimen>
<dimen name="list_item_object_subtitle_margin_end">20dp</dimen>
<dimen name="list_item_object_emoji_size">24dp</dimen>
<dimen name="list_item_object_checkbox_size">24dp</dimen>
<dimen name="list_item_object_subtitle_margin_start">16dp</dimen>
<dimen name="list_item_object_subtitle_margin_end">16dp</dimen>
<dimen name="list_item_object_emoji_size">28dp</dimen>
<dimen name="list_item_object_checkbox_size">22dp</dimen>
<dimen name="list_item_object_initials_size">28sp</dimen>
<dimen name="list_item_object_image_corner_radius">2dp</dimen>
<dimen name="list_item_object_image_corner_radius_small">1dp</dimen>

View file

@ -507,11 +507,11 @@
</style>
<!-- Object items in lists -->
<style name="ObjectListItemTitle" parent="TextView.UXStyle.Titles.2.Regular">
<style name="ObjectListItemTitle" parent="TextView.ContentStyle.PreviewTitles.2.Medium">
<item name="android:textColorHint">@color/text_tertiary</item>
</style>
<style name="ObjectListItemSubtitle" parent="TextView.ContentStyle.Relations.2">
<style name="ObjectListItemSubtitle" parent="TextView.UXStyle.Captions.1.Regular">
<item name="android:textColor">@color/text_secondary</item>
</style>

View file

@ -104,7 +104,8 @@ class CellViewDiffUtilTest {
id = MockDataFactory.randomString(),
relationKey = MockDataFactory.randomString(),
timeInSecs = MockDataFactory.randomLong(),
dateFormat = MockDataFactory.randomString()
dateFormat = MockDataFactory.randomString(),
relativeDate = null
)
val newCell = oldCell.copy(
@ -127,7 +128,8 @@ class CellViewDiffUtilTest {
val oldCell = CellView.Date(
id = MockDataFactory.randomString(),
relationKey = MockDataFactory.randomString(),
dateFormat = MockDataFactory.randomString()
dateFormat = MockDataFactory.randomString(),
relativeDate = null
)
val newCell = oldCell.copy()

Some files were not shown because too many files have changed in this diff Show more