Compare commits
63 Commits
main
...
droid-1949
Author | SHA1 | Date | |
---|---|---|---|
|
e8bbfec912 | ||
|
7ad158e7ed | ||
|
ef49cfe6bf | ||
|
dab2ac2e54 | ||
|
dcb80495de | ||
|
82a20883f3 | ||
|
e0ce5dffbb | ||
|
3e09dc516a | ||
|
ae3dc2ef80 | ||
|
11e1bc7600 | ||
|
9ec69ce50d | ||
|
1cd675563c | ||
|
bd20fb9a19 | ||
|
7f38e77f53 | ||
|
e656540b7e | ||
|
5ca83e11ce | ||
|
8667389f17 | ||
|
fe847c6416 | ||
|
0ed7004469 | ||
|
e958d1d0ca | ||
|
1b59726142 | ||
|
4c3d20c989 | ||
|
c78e09d724 | ||
|
cc1868ad9e | ||
|
c95cc66b5e | ||
|
9561af3164 | ||
|
5c2bcda941 | ||
|
d6f7c7737b | ||
|
55fc4a2da7 | ||
|
29c70708ca | ||
|
06048dfec5 | ||
|
e71014931c | ||
|
49f9fef100 | ||
|
eaf5cf386a | ||
|
b2027538cb | ||
|
2d4cde60c4 | ||
|
f87fad40ef | ||
|
3ba407ab18 | ||
|
4a11f304e7 | ||
|
68c5d67ed6 | ||
|
b33817d558 | ||
|
2673b5bfc5 | ||
|
06e9e581bc | ||
|
154545b7a7 | ||
|
201987e705 | ||
|
4128c82e14 | ||
|
49fef69df0 | ||
|
290767c598 | ||
|
21e4ab8523 | ||
|
6bc114676d | ||
|
242d6b41e6 | ||
|
95d4c055c3 | ||
|
c75342bc34 | ||
|
799d0dd951 | ||
|
1e6d2f2b97 | ||
|
9fc67d4c8b | ||
|
fa564f7109 | ||
|
83d9ad8a4c | ||
|
f7029501dd | ||
|
018a3bb62b | ||
|
372bfa4375 | ||
|
a9d75d8d57 | ||
|
7672503414 |
|
@ -20,6 +20,13 @@ object EventsDictionary {
|
|||
// Settings events
|
||||
|
||||
const val screenSettingSpacesSpaceIndex = "ScreenSettingsSpaceIndex"
|
||||
const val screenSettingsAccount = "ScreenSettingsAccount"
|
||||
const val clickDeleteSpace = "ClickDeleteSpace"
|
||||
const val clickDeleteSpaceWarning = "ClickDeleteSpaceWarning"
|
||||
const val createSpace = "CreateSpace"
|
||||
const val switchSpace = "SwitchSpace"
|
||||
const val deleteSpace = "DeleteSpace"
|
||||
const val screenSettingsSpaceCreate = "ScreenSettingsSpaceCreate"
|
||||
|
||||
|
||||
const val wallpaperSet = "SettingsWallpaperSet"
|
||||
|
@ -48,6 +55,7 @@ object EventsDictionary {
|
|||
const val appearanceScreenShow = "ScreenSettingsAppearance"
|
||||
const val screenSettingsStorage = "ScreenSettingsStorageIndex"
|
||||
const val screenSettingsStorageManage = "ScreenSettingsStorageManager"
|
||||
const val screenSettingsSpaceStorageManager = "ScreenSettingsSpaceStorageManager"
|
||||
const val screenSettingsStorageOffload = "ScreenFileOffloadWarning"
|
||||
const val settingsStorageOffload = "SettingsStorageOffload"
|
||||
const val screenSettingsDelete = "ScreenSettingsDelete"
|
||||
|
@ -57,6 +65,7 @@ object EventsDictionary {
|
|||
const val searchResult = "SearchResult"
|
||||
const val searchWords = "SearchWords"
|
||||
const val objectTypeChanged = "ChangeObjectType"
|
||||
const val selectObjectType = "SelectObjectType"
|
||||
const val objectLayoutChange = "ChangeLayout"
|
||||
const val objectSetIcon = "SetIcon"
|
||||
const val objectRemoveIcon = "RemoveIcon"
|
||||
|
@ -206,6 +215,7 @@ object EventsDictionary {
|
|||
const val objPowerTool = "Powertool"
|
||||
const val objTurnInto = "TurnInto"
|
||||
const val screenSettings = "ScreenSettings"
|
||||
const val settings = "Settings"
|
||||
const val screenDeletion = "ScreenDeletion"
|
||||
const val navigation = "Navigation"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
version.versionMajor=0
|
||||
version.versionMinor=26
|
||||
version.versionPatch=0
|
||||
version.versionPatch=11
|
||||
version.useDatedVersionName=false
|
|
@ -559,7 +559,7 @@ open class EditorTestSetup {
|
|||
repo.stub {
|
||||
onBlocking {
|
||||
searchObjects(
|
||||
filters = ObjectSearchConstants.filterObjectTypeLibrary(workspaceId),
|
||||
filters = ObjectSearchConstants.filterTypes(workspaceId),
|
||||
keys = ObjectSearchConstants.defaultKeysObjectType,
|
||||
sorts = emptyList(),
|
||||
limit = 0,
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
|||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.Result
|
||||
import com.anytypeio.anytype.domain.block.interactor.UpdateText
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.collections.AddObjectToCollection
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
|
@ -150,6 +151,9 @@ abstract class TestObjectSetSetup {
|
|||
@Mock
|
||||
lateinit var configStorage: ConfigStorage
|
||||
|
||||
@Mock
|
||||
lateinit var getObjectTypes: GetObjectTypes
|
||||
|
||||
@Mock
|
||||
lateinit var createTemplate: CreateTemplate
|
||||
|
||||
|
@ -265,14 +269,13 @@ abstract class TestObjectSetSetup {
|
|||
objectStore = objectStore,
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
getDefaultObjectType = getDefaultObjectType,
|
||||
updateDataViewViewer = updateDataViewViewer,
|
||||
templatesContainer = templatesContainer,
|
||||
setObjectListIsArchived = setObjectListIsArchived,
|
||||
duplicateObjects = duplicateObjects,
|
||||
viewerDelegate = viewerDelegate,
|
||||
spaceManager = spaceManager,
|
||||
createTemplate = createTemplate
|
||||
createTemplate = createTemplate,
|
||||
getObjectTypes = getObjectTypes
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.anytypeio.anytype.di.common
|
|||
import android.content.Context
|
||||
import com.anytypeio.anytype.BuildConfig
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.di.feature.AddDataViewRelationObjectValueModule
|
||||
import com.anytypeio.anytype.di.feature.AddDataViewRelationOptionValueModule
|
||||
import com.anytypeio.anytype.di.feature.AddFileRelationModule
|
||||
import com.anytypeio.anytype.di.feature.AddObjectRelationModule
|
||||
import com.anytypeio.anytype.di.feature.AddObjectRelationValueModule
|
||||
|
@ -64,6 +66,7 @@ import com.anytypeio.anytype.di.feature.auth.DaggerDeletedAccountComponent
|
|||
import com.anytypeio.anytype.di.feature.cover.UnsplashModule
|
||||
import com.anytypeio.anytype.di.feature.home.DaggerHomeScreenComponent
|
||||
import com.anytypeio.anytype.di.feature.library.DaggerLibraryComponent
|
||||
import com.anytypeio.anytype.di.feature.objects.DaggerCreateObjectOfTypeComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.DaggerOnboardingComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.DaggerOnboardingStartComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.login.DaggerOnboardingLoginSetupComponent
|
||||
|
@ -71,7 +74,6 @@ import com.anytypeio.anytype.di.feature.onboarding.login.DaggerOnboardingMnemoni
|
|||
import com.anytypeio.anytype.di.feature.onboarding.signup.DaggerOnboardingMnemonicComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.signup.DaggerOnboardingSoulCreationAnimComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.signup.DaggerOnboardingSoulCreationComponent
|
||||
import com.anytypeio.anytype.di.feature.onboarding.signup.DaggerOnboardingVoidComponent
|
||||
import com.anytypeio.anytype.di.feature.relations.DaggerRelationCreateFromLibraryComponent
|
||||
import com.anytypeio.anytype.di.feature.relations.DaggerRelationEditComponent
|
||||
import com.anytypeio.anytype.di.feature.relations.LimitObjectTypeModule
|
||||
|
@ -89,6 +91,7 @@ import com.anytypeio.anytype.di.feature.sets.viewer.ViewerImagePreviewSelectModu
|
|||
import com.anytypeio.anytype.di.feature.settings.DaggerAboutAppComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerAppearanceComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerFilesStorageComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.DaggerSpacesStorageComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.LogoutWarningModule
|
||||
import com.anytypeio.anytype.di.feature.settings.MainSettingsModule
|
||||
import com.anytypeio.anytype.di.feature.settings.ProfileModule
|
||||
|
@ -374,7 +377,7 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val dataViewRelationListComponent = DependentComponentMap { id ->
|
||||
val objectSetRelationListComponent = DependentComponentMap { id ->
|
||||
objectSetComponent
|
||||
.get(id)
|
||||
.objectRelationListComponent()
|
||||
|
@ -494,6 +497,14 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val addDataViewObjectRelationValueComponent = DependentComponentMap { ctx ->
|
||||
dataViewRelationValueComponent
|
||||
.get(ctx)
|
||||
.addDataViewRelationOptionValueComponent()
|
||||
.module(AddDataViewRelationOptionValueModule)
|
||||
.build()
|
||||
}
|
||||
|
||||
val objectObjectRelationValueComponent = DependentComponentMap { ctx ->
|
||||
editorComponent
|
||||
.get(ctx)
|
||||
|
@ -518,6 +529,14 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val addDataViewRelationObjectValueComponent = DependentComponentMap { ctx ->
|
||||
dataViewRelationValueComponent
|
||||
.get(ctx)
|
||||
.addDataViewRelationObjectValueComponent()
|
||||
.module(AddDataViewRelationObjectValueModule)
|
||||
.build()
|
||||
}
|
||||
|
||||
val addObjectRelationObjectValueComponent = DependentComponentMap { ctx ->
|
||||
objectObjectRelationValueComponent
|
||||
.get(ctx)
|
||||
|
@ -848,6 +867,12 @@ class ComponentManager(
|
|||
.build()
|
||||
}
|
||||
|
||||
val spacesStorageComponent = Component {
|
||||
DaggerSpacesStorageComponent.builder()
|
||||
.withDependencies(findComponentDependencies())
|
||||
.build()
|
||||
}
|
||||
|
||||
val appearanceComponent = Component {
|
||||
DaggerAppearanceComponent
|
||||
.factory()
|
||||
|
@ -928,12 +953,6 @@ class ComponentManager(
|
|||
.create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val onboardingNewVoidComponent = Component {
|
||||
DaggerOnboardingVoidComponent
|
||||
.factory()
|
||||
.create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val onboardingMnemonicComponent = Component {
|
||||
DaggerOnboardingMnemonicComponent
|
||||
.factory()
|
||||
|
@ -982,6 +1001,13 @@ class ComponentManager(
|
|||
.create(findComponentDependencies())
|
||||
}
|
||||
|
||||
val createObjectOfTypeComponent = Component {
|
||||
DaggerCreateObjectOfTypeComponent
|
||||
.factory()
|
||||
.create(findComponentDependencies())
|
||||
}
|
||||
|
||||
|
||||
class Component<T>(private val builder: () -> T) {
|
||||
|
||||
private var instance: T? = null
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
package com.anytypeio.anytype.di.feature
|
||||
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerDialog
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.relations.add.AddObjectRelationViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
|
||||
import com.anytypeio.anytype.ui.relations.add.AddObjectRelationFragment
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.Subcomponent
|
||||
import javax.inject.Named
|
||||
|
||||
@Subcomponent(modules = [AddDataViewRelationObjectValueModule::class])
|
||||
@PerDialog
|
||||
interface AddDataViewRelationObjectValueSubComponent {
|
||||
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
fun module(module: AddDataViewRelationObjectValueModule): Builder
|
||||
fun build(): AddDataViewRelationObjectValueSubComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: AddObjectRelationFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object AddDataViewRelationObjectValueModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideViewModelFactory(
|
||||
@Named(ObjectRelationProvider.DATA_VIEW_PROVIDER_TYPE) relations: ObjectRelationProvider,
|
||||
@Named(ObjectRelationProvider.DATA_VIEW_PROVIDER_TYPE) values: ObjectValueProvider,
|
||||
storeOfObjectTypes: StoreOfObjectTypes,
|
||||
searchObjects: SearchObjects,
|
||||
urlBuilder: UrlBuilder,
|
||||
spaceManager: SpaceManager
|
||||
): AddObjectRelationViewModel.Factory = AddObjectRelationViewModel.Factory(
|
||||
relations = relations,
|
||||
values = values,
|
||||
searchObjects = searchObjects,
|
||||
urlBuilder = urlBuilder,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
spaceManager = spaceManager
|
||||
)
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.presentation.relations.add.AddOptionsRelationProvid
|
|||
import com.anytypeio.anytype.presentation.relations.add.AddOptionsRelationViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectDetailProvider
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.DATA_VIEW_PROVIDER_TYPE
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.INTRINSIC_PROVIDER_TYPE
|
||||
import com.anytypeio.anytype.presentation.relations.providers.ObjectValueProvider
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
|
@ -36,6 +37,18 @@ interface AddObjectRelationValueSubComponent {
|
|||
fun inject(fragment: AddOptionsRelationFragment)
|
||||
}
|
||||
|
||||
@Subcomponent(modules = [AddDataViewRelationOptionValueModule::class])
|
||||
@PerDialog
|
||||
interface AddDataViewRelationOptionValueSubComponent {
|
||||
@Subcomponent.Builder
|
||||
interface Builder {
|
||||
fun module(module: AddDataViewRelationOptionValueModule): Builder
|
||||
fun build(): AddDataViewRelationOptionValueSubComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: AddOptionsRelationDVFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object AddObjectRelationValueModule {
|
||||
|
||||
|
@ -91,6 +104,43 @@ object AddObjectRelationValueModule {
|
|||
spaceManager = spaceManager
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun createRelationOption(
|
||||
repo: BlockRepository
|
||||
): CreateRelationOption = CreateRelationOption(repo = repo)
|
||||
}
|
||||
|
||||
@Module
|
||||
object AddDataViewRelationOptionValueModule {
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun provideViewModelFactoryForDataView(
|
||||
@Named(DATA_VIEW_PROVIDER_TYPE) relations: ObjectRelationProvider,
|
||||
@Named(DATA_VIEW_PROVIDER_TYPE) values: ObjectValueProvider,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
createRelationOption: CreateRelationOption,
|
||||
analytics: Analytics,
|
||||
setObjectDetail: UpdateDetail,
|
||||
detailsProvider: ObjectDetailProvider,
|
||||
getOptions: GetOptions,
|
||||
spaceManager: SpaceManager
|
||||
): AddOptionsRelationDVViewModel.Factory = AddOptionsRelationDVViewModel.Factory(
|
||||
relations = relations,
|
||||
values = values,
|
||||
dispatcher = dispatcher,
|
||||
createRelationOption = createRelationOption,
|
||||
optionsProvider = AddOptionsRelationProvider(),
|
||||
analytics = analytics,
|
||||
setObjectDetail = setObjectDetail,
|
||||
detailsProvider = detailsProvider,
|
||||
getOptions = getOptions,
|
||||
spaceManager = spaceManager
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.device.PathProvider
|
|||
import com.anytypeio.anytype.domain.platform.MetricsProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.theme.GetTheme
|
||||
import com.anytypeio.anytype.domain.wallpaper.ObserveWallpaper
|
||||
import com.anytypeio.anytype.domain.wallpaper.RestoreWallpaper
|
||||
|
@ -45,6 +46,7 @@ interface MainEntrySubComponent {
|
|||
|
||||
@Module
|
||||
object MainEntryModule {
|
||||
|
||||
@JvmStatic
|
||||
@PerScreen
|
||||
@Provides
|
||||
|
@ -58,7 +60,8 @@ object MainEntryModule {
|
|||
relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
checkAuthorizationStatus: CheckAuthorizationStatus,
|
||||
configStorage: ConfigStorage
|
||||
configStorage: ConfigStorage,
|
||||
spaceDeletedStatusWatcher: SpaceDeletedStatusWatcher
|
||||
): MainViewModelFactory = MainViewModelFactory(
|
||||
resumeAccount = resumeAccount,
|
||||
analytics = analytics,
|
||||
|
@ -69,7 +72,8 @@ object MainEntryModule {
|
|||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager,
|
||||
checkAuthorizationStatus = checkAuthorizationStatus,
|
||||
configStorage = configStorage
|
||||
configStorage = configStorage,
|
||||
spaceDeletedStatusWatcher = spaceDeletedStatusWatcher
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.anytypeio.anytype.di.feature
|
||||
|
||||
import android.content.Context
|
||||
import com.anytypeio.anytype.analytics.base.Analytics
|
||||
import com.anytypeio.anytype.core_models.Payload
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerDialog
|
||||
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
||||
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
|
||||
import com.anytypeio.anytype.domain.`object`.DuplicateObject
|
||||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
|
@ -30,7 +30,9 @@ import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuViewModel
|
|||
import com.anytypeio.anytype.presentation.objects.menu.ObjectSetMenuViewModel
|
||||
import com.anytypeio.anytype.presentation.sets.state.ObjectState
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DebugGoroutinesShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.DebugTreeShareDownloader
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuFragment
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetMenuFragment
|
||||
import dagger.Module
|
||||
|
@ -117,7 +119,8 @@ object ObjectMenuModule {
|
|||
delegator: Delegator<Action>,
|
||||
addObjectToCollection: AddObjectToCollection,
|
||||
createTemplateFromObject: CreateTemplateFromObject,
|
||||
setObjectDetails: SetObjectDetails
|
||||
setObjectDetails: SetObjectDetails,
|
||||
debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader
|
||||
): ObjectMenuViewModel.Factory = ObjectMenuViewModel.Factory(
|
||||
setObjectIsArchived = setObjectIsArchived,
|
||||
duplicateObject = duplicateObject,
|
||||
|
@ -134,7 +137,8 @@ object ObjectMenuModule {
|
|||
menuOptionsProvider = createMenuOptionsProvider(storage, featureToggles),
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
createTemplateFromObject = createTemplateFromObject,
|
||||
setObjectDetails = setObjectDetails
|
||||
setObjectDetails = setObjectDetails,
|
||||
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -166,6 +170,21 @@ object ObjectMenuModule {
|
|||
repo = repo,
|
||||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun debugGoRoutines(
|
||||
repo: BlockRepository,
|
||||
context: Context,
|
||||
fileProvider: UriFileProvider,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): DebugGoroutinesShareDownloader = DebugGoroutinesShareDownloader(
|
||||
repo = repo,
|
||||
context = context.applicationContext,
|
||||
uriFileProvider = fileProvider,
|
||||
dispatchers = dispatchers
|
||||
)
|
||||
}
|
||||
|
||||
@Module
|
||||
|
@ -186,7 +205,8 @@ object ObjectSetMenuModule {
|
|||
state: MutableStateFlow<ObjectState>,
|
||||
featureToggles: FeatureToggles,
|
||||
dispatcher: Dispatcher<Payload>,
|
||||
addObjectToCollection: AddObjectToCollection
|
||||
addObjectToCollection: AddObjectToCollection,
|
||||
debugGoroutinesShareDownloader: DebugGoroutinesShareDownloader
|
||||
): ObjectSetMenuViewModel.Factory = ObjectSetMenuViewModel.Factory(
|
||||
setObjectIsArchived = setObjectIsArchived,
|
||||
addToFavorite = addToFavorite,
|
||||
|
@ -199,7 +219,8 @@ object ObjectSetMenuModule {
|
|||
objectState = state,
|
||||
dispatcher = dispatcher,
|
||||
menuOptionsProvider = createMenuOptionsProvider(state, featureToggles),
|
||||
addObjectToCollection = addObjectToCollection
|
||||
addObjectToCollection = addObjectToCollection,
|
||||
debugGoroutinesShareDownloader = debugGoroutinesShareDownloader
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -222,6 +243,21 @@ object ObjectSetMenuModule {
|
|||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerDialog
|
||||
fun debugGoRoutines(
|
||||
repo: BlockRepository,
|
||||
context: Context,
|
||||
fileProvider: UriFileProvider,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): DebugGoroutinesShareDownloader = DebugGoroutinesShareDownloader(
|
||||
repo = repo,
|
||||
context = context.applicationContext,
|
||||
uriFileProvider = fileProvider,
|
||||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
private fun createMenuOptionsProvider(
|
||||
state: StateFlow<ObjectState>,
|
||||
|
|
|
@ -38,6 +38,9 @@ interface DataViewObjectRelationValueSubComponent {
|
|||
fun addObjectRelationValueComponent(): AddObjectRelationValueSubComponent.Builder
|
||||
fun addObjectRelationObjectValueComponent(): AddObjectRelationSubComponent.Builder
|
||||
fun addRelationFileValueAddComponent() : AddFileRelationSubComponent.Builder
|
||||
|
||||
fun addDataViewRelationOptionValueComponent(): AddDataViewRelationOptionValueSubComponent.Builder
|
||||
fun addDataViewRelationObjectValueComponent(): AddDataViewRelationObjectValueSubComponent.Builder
|
||||
}
|
||||
|
||||
@Subcomponent(modules = [SetOrCollectionRelationValueModule::class])
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.di.feature.sets.viewer.ViewerImagePreviewSelectSubc
|
|||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.interactor.UpdateText
|
||||
import com.anytypeio.anytype.domain.block.interactor.sets.GetObjectTypes
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import com.anytypeio.anytype.domain.collections.AddObjectToCollection
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
|
@ -93,7 +94,9 @@ import com.anytypeio.anytype.presentation.templates.ObjectTypeTemplatesContainer
|
|||
import com.anytypeio.anytype.presentation.util.CopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.DefaultCopyFileToCacheDirectory
|
||||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.providers.DefaultCoverImageHashProvider
|
||||
import com.anytypeio.anytype.providers.DefaultUriFileProvider
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
|
@ -186,6 +189,14 @@ object ObjectSetModule {
|
|||
dispatchers = dispatchers
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetObjectTypesUseCase(
|
||||
repository: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): GetObjectTypes = GetObjectTypes(repository, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
|
@ -218,8 +229,7 @@ object ObjectSetModule {
|
|||
addObjectToCollection: AddObjectToCollection,
|
||||
convertObjectToCollection: ConvertObjectToCollection,
|
||||
storeOfObjectTypes: StoreOfObjectTypes,
|
||||
getDefaultObjectType: GetDefaultObjectType,
|
||||
updateDataViewViewer: UpdateDataViewViewer,
|
||||
getObjectTypes: GetObjectTypes,
|
||||
duplicateObjects: DuplicateObjects,
|
||||
templatesContainer: ObjectTypeTemplatesContainer,
|
||||
setObjectListIsArchived: SetObjectListIsArchived,
|
||||
|
@ -255,8 +265,7 @@ object ObjectSetModule {
|
|||
addObjectToCollection = addObjectToCollection,
|
||||
objectToCollection = convertObjectToCollection,
|
||||
storeOfObjectTypes = storeOfObjectTypes,
|
||||
getDefaultObjectType = getDefaultObjectType,
|
||||
updateDataViewViewer = updateDataViewViewer,
|
||||
getObjectTypes = getObjectTypes,
|
||||
duplicateObjects = duplicateObjects,
|
||||
templatesContainer = templatesContainer,
|
||||
setObjectListIsArchived = setObjectListIsArchived,
|
||||
|
@ -639,6 +648,12 @@ object ObjectSetModule {
|
|||
fun bindCoverImageHashProvider(
|
||||
defaultProvider: DefaultCoverImageHashProvider
|
||||
): CoverImageHashProvider
|
||||
|
||||
@PerScreen
|
||||
@Binds
|
||||
fun bindUriFileProvider(
|
||||
defaultProvider: DefaultUriFileProvider
|
||||
): UriFileProvider
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -24,9 +24,9 @@ import com.anytypeio.anytype.domain.page.CreateObject
|
|||
import com.anytypeio.anytype.domain.platform.MetricsProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.templates.GetTemplates
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
import com.anytypeio.anytype.presentation.splash.SplashViewModelFactory
|
||||
import com.anytypeio.anytype.ui.splash.SplashFragment
|
||||
import dagger.Binds
|
||||
|
@ -175,7 +175,6 @@ object SplashModule {
|
|||
|
||||
interface SplashDependencies : ComponentDependencies {
|
||||
fun blockRepository(): BlockRepository
|
||||
fun workspaceManager(): WorkspaceManager
|
||||
fun urlBuilder(): UrlBuilder
|
||||
fun analytics(): Analytics
|
||||
fun relationsSubscriptionManager(): RelationsSubscriptionManager
|
||||
|
@ -190,4 +189,5 @@ interface SplashDependencies : ComponentDependencies {
|
|||
fun crashReporter(): CrashReporter
|
||||
fun metricsProvider(): MetricsProvider
|
||||
fun spaceManager(): SpaceManager
|
||||
fun spaceStatusWatcher(): SpaceDeletedStatusWatcher
|
||||
}
|
|
@ -12,7 +12,9 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.misc.AppActionManager
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.ext.DefaultDateHelper
|
||||
import com.anytypeio.anytype.presentation.auth.account.DeletedAccountViewModel
|
||||
|
@ -91,10 +93,13 @@ object DeletedAccountModule {
|
|||
interface DeletedAccountDependencies : ComponentDependencies {
|
||||
fun analytics(): Analytics
|
||||
fun appActionManager(): AppActionManager
|
||||
fun relationsSubscriptionManager(): RelationsSubscriptionManager
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun configStorage(): ConfigStorage
|
||||
fun authRepository(): AuthRepository
|
||||
fun userSettingsRepository(): UserSettingsRepository
|
||||
fun spaceManager(): SpaceManager
|
||||
|
||||
fun relationsSubscriptionManager(): RelationsSubscriptionManager
|
||||
fun objectTypesSubscriptionManager(): ObjectTypesSubscriptionManager
|
||||
fun spaceDeletedStatusWatcher(): SpaceDeletedStatusWatcher
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.anytypeio.anytype.di.feature.objects
|
||||
|
||||
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.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.objects.CreateObjectOfTypeViewModel
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
|
||||
@Component(
|
||||
dependencies = [CreateObjectOfTypeDependencies::class],
|
||||
modules = [
|
||||
CreateObjectOfTypeModule::class,
|
||||
CreateObjectOfTypeModule.Declarations::class
|
||||
]
|
||||
)
|
||||
@PerScreen
|
||||
interface CreateObjectOfTypeComponent {
|
||||
@Component.Factory
|
||||
interface Builder {
|
||||
fun create(dependencies: CreateObjectOfTypeDependencies): CreateObjectOfTypeComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: CreateObjectOfTypeFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object CreateObjectOfTypeModule {
|
||||
@Module
|
||||
interface Declarations {
|
||||
@Binds
|
||||
@PerScreen
|
||||
fun bindViewModelFactory(factory: CreateObjectOfTypeViewModel.Factory): ViewModelProvider.Factory
|
||||
}
|
||||
}
|
||||
|
||||
interface CreateObjectOfTypeDependencies : ComponentDependencies {
|
||||
fun repo(): BlockRepository
|
||||
fun analytics(): Analytics
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun spaceManager(): SpaceManager
|
||||
}
|
|
@ -12,7 +12,7 @@ import com.anytypeio.anytype.domain.device.PathProvider
|
|||
import com.anytypeio.anytype.domain.platform.MetricsProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingLoginSetupViewModel
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
|
@ -55,9 +55,9 @@ interface OnboardingLoginSetupDependencies : ComponentDependencies {
|
|||
fun pathProvider(): PathProvider
|
||||
fun crashReporter(): CrashReporter
|
||||
fun configStorage(): ConfigStorage
|
||||
fun workspaceManager(): WorkspaceManager
|
||||
fun featureConfigProvider(): FeaturesConfigProvider
|
||||
fun metricsProvider(): MetricsProvider
|
||||
fun objectTypesSubscriptionManager(): ObjectTypesSubscriptionManager
|
||||
fun relationsSubscriptionManager(): RelationsSubscriptionManager
|
||||
fun spaceStatusWatcher(): SpaceDeletedStatusWatcher
|
||||
}
|
|
@ -16,6 +16,7 @@ import com.anytypeio.anytype.domain.`object`.SetupMobileUseCaseSkip
|
|||
import com.anytypeio.anytype.domain.platform.MetricsProvider
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
|
||||
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingSetProfileNameViewModel
|
||||
|
@ -107,6 +108,7 @@ interface OnboardingSoulCreationDependencies : ComponentDependencies {
|
|||
fun metricsProvider(): MetricsProvider
|
||||
fun crashReporter(): CrashReporter
|
||||
fun spaceManager(): SpaceManager
|
||||
fun spaceStatusWatcher(): SpaceDeletedStatusWatcher
|
||||
}
|
||||
|
||||
@Scope
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.di.feature.relations
|
|||
import com.anytypeio.anytype.core_utils.di.scope.PerDialog
|
||||
import com.anytypeio.anytype.domain.search.SearchObjects
|
||||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.relations.LimitObjectTypeViewModel
|
||||
import com.anytypeio.anytype.presentation.relations.model.CreateFromScratchState
|
||||
import com.anytypeio.anytype.presentation.relations.model.StateHolder
|
||||
|
@ -32,10 +33,12 @@ object LimitObjectTypeModule {
|
|||
fun provideViewModelFactory(
|
||||
searchObjects: SearchObjects,
|
||||
urlBuilder: UrlBuilder,
|
||||
state: StateHolder<CreateFromScratchState>
|
||||
state: StateHolder<CreateFromScratchState>,
|
||||
spaceManager: SpaceManager
|
||||
): LimitObjectTypeViewModel.Factory = LimitObjectTypeViewModel.Factory(
|
||||
searchObjects = searchObjects,
|
||||
urlBuilder = urlBuilder,
|
||||
state = state
|
||||
state = state,
|
||||
spaceManager = spaceManager
|
||||
)
|
||||
}
|
|
@ -6,7 +6,6 @@ import com.anytypeio.anytype.core_utils.di.scope.PerScreen
|
|||
import com.anytypeio.anytype.device.BuildProvider
|
||||
import com.anytypeio.anytype.di.common.ComponentDependencies
|
||||
import com.anytypeio.anytype.domain.account.DeleteAccount
|
||||
import com.anytypeio.anytype.domain.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
@ -17,7 +16,7 @@ import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
|||
import com.anytypeio.anytype.domain.misc.UrlBuilder
|
||||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
|
||||
import com.anytypeio.anytype.domain.workspace.FileSpaceUsage
|
||||
import com.anytypeio.anytype.domain.workspace.SpacesUsageInfo
|
||||
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.settings.FilesStorageViewModel
|
||||
|
@ -81,9 +80,8 @@ object FilesStorageModule {
|
|||
@PerScreen
|
||||
fun provideSpaceUsage(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers,
|
||||
spaceManager: SpaceManager
|
||||
): FileSpaceUsage = FileSpaceUsage(repo, spaceManager, dispatchers)
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): SpacesUsageInfo = SpacesUsageInfo(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
|
@ -93,14 +91,6 @@ object FilesStorageModule {
|
|||
dispatchers: AppCoroutineDispatchers
|
||||
) : InterceptFileLimitEvents = InterceptFileLimitEvents(channel, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetAccountUseCase(
|
||||
repo: AuthRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): GetAccount = GetAccount(repo = repo, dispatcher = dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
|
|
|
@ -8,7 +8,9 @@ import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
|||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.config.UserSettingsRepository
|
||||
import com.anytypeio.anytype.domain.misc.AppActionManager
|
||||
import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.ui.settings.LogoutWarningFragment
|
||||
import com.anytypeio.anytype.ui_settings.account.LogoutWarningViewModel
|
||||
|
@ -39,12 +41,16 @@ object LogoutWarningModule {
|
|||
logout: Logout,
|
||||
analytics: Analytics,
|
||||
relationsSubscriptionManager: RelationsSubscriptionManager,
|
||||
appActionManager: AppActionManager
|
||||
objectTypesSubscriptionManager: ObjectTypesSubscriptionManager,
|
||||
spaceDeletedStatusWatcher: SpaceDeletedStatusWatcher,
|
||||
appActionManager: AppActionManager,
|
||||
): LogoutWarningViewModel.Factory = LogoutWarningViewModel.Factory(
|
||||
logout = logout,
|
||||
analytics = analytics,
|
||||
relationsSubscriptionManager = relationsSubscriptionManager,
|
||||
appActionManager = appActionManager
|
||||
appActionManager = appActionManager,
|
||||
spaceDeletedStatusWatcher = spaceDeletedStatusWatcher,
|
||||
objectTypesSubscriptionManager = objectTypesSubscriptionManager
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -48,8 +48,7 @@ object ProfileModule {
|
|||
setObjectDetails: SetObjectDetails,
|
||||
configStorage: ConfigStorage,
|
||||
urlBuilder: UrlBuilder,
|
||||
setDocumentImageIcon: SetDocumentImageIcon,
|
||||
spaceGradientProvider: SpaceGradientProvider
|
||||
setDocumentImageIcon: SetDocumentImageIcon
|
||||
): ProfileSettingsViewModel.Factory = ProfileSettingsViewModel.Factory(
|
||||
deleteAccount = deleteAccount,
|
||||
analytics = analytics,
|
||||
|
@ -57,8 +56,7 @@ object ProfileModule {
|
|||
setObjectDetails = setObjectDetails,
|
||||
configStorage = configStorage,
|
||||
urlBuilder = urlBuilder,
|
||||
setDocumentImageIcon = setDocumentImageIcon,
|
||||
spaceGradientProvider = spaceGradientProvider
|
||||
setDocumentImageIcon = setDocumentImageIcon
|
||||
)
|
||||
|
||||
@Provides
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package com.anytypeio.anytype.di.feature.settings
|
||||
|
||||
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.auth.interactor.GetAccount
|
||||
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
|
||||
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.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.workspace.FileLimitsEventChannel
|
||||
import com.anytypeio.anytype.domain.workspace.SpacesUsageInfo
|
||||
import com.anytypeio.anytype.domain.workspace.InterceptFileLimitEvents
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModelFactory
|
||||
import com.anytypeio.anytype.ui.settings.SpacesStorageFragment
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
||||
@PerScreen
|
||||
@Component(
|
||||
dependencies = [SpacesStorageDependencies::class],
|
||||
modules = [
|
||||
SpacesStorageModule::class,
|
||||
SpacesStorageModule.Declarations::class
|
||||
]
|
||||
)
|
||||
interface SpacesStorageComponent {
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
|
||||
fun withDependencies(dependency: SpacesStorageDependencies): Builder
|
||||
fun build(): SpacesStorageComponent
|
||||
}
|
||||
|
||||
fun inject(fragment: SpacesStorageFragment)
|
||||
}
|
||||
|
||||
@Module
|
||||
object SpacesStorageModule {
|
||||
|
||||
@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 provideSpaceUsage(
|
||||
repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): SpacesUsageInfo = SpacesUsageInfo(repo, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideFileLimitEvents(
|
||||
channel: FileLimitsEventChannel,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : InterceptFileLimitEvents = InterceptFileLimitEvents(channel, dispatchers)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@PerScreen
|
||||
fun provideGetAccountUseCase(
|
||||
repo: AuthRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): GetAccount = GetAccount(repo = repo, dispatcher = dispatchers)
|
||||
|
||||
@Module
|
||||
interface Declarations {
|
||||
|
||||
@PerScreen
|
||||
@Binds
|
||||
fun bindViewModelFactory(factory: SpacesStorageViewModelFactory): ViewModelProvider.Factory
|
||||
}
|
||||
}
|
||||
|
||||
interface SpacesStorageDependencies : ComponentDependencies {
|
||||
fun blockRepo(): BlockRepository
|
||||
fun dispatchers(): AppCoroutineDispatchers
|
||||
fun analytics(): Analytics
|
||||
fun configStorage(): ConfigStorage
|
||||
fun channel(): SubscriptionEventChannel
|
||||
fun fileEventsChannel(): FileLimitsEventChannel
|
||||
fun authRepo(): AuthRepository
|
||||
fun logger(): Logger
|
||||
fun spaceManager(): SpaceManager
|
||||
}
|
|
@ -8,8 +8,11 @@ import com.anytypeio.anytype.domain.debugging.Logger
|
|||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
|
||||
@Module
|
||||
object ConfigModule {
|
||||
|
@ -38,4 +41,14 @@ object ConfigModule {
|
|||
computation = Dispatchers.Default,
|
||||
main = Dispatchers.Main
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(DEFAULT_APP_COROUTINE_SCOPE)
|
||||
fun applicationCoroutineScope() : CoroutineScope = CoroutineScope(
|
||||
SupervisorJob() + Dispatchers.Default
|
||||
)
|
||||
|
||||
const val DEFAULT_APP_COROUTINE_SCOPE = "Default application coroutine scope"
|
||||
}
|
|
@ -21,6 +21,7 @@ import com.anytypeio.anytype.di.feature.SplashDependencies
|
|||
import com.anytypeio.anytype.di.feature.auth.DeletedAccountDependencies
|
||||
import com.anytypeio.anytype.di.feature.home.HomeScreenDependencies
|
||||
import com.anytypeio.anytype.di.feature.library.LibraryDependencies
|
||||
import com.anytypeio.anytype.di.feature.objects.CreateObjectOfTypeDependencies
|
||||
import com.anytypeio.anytype.di.feature.onboarding.OnboardingDependencies
|
||||
import com.anytypeio.anytype.di.feature.onboarding.OnboardingStartDependencies
|
||||
import com.anytypeio.anytype.di.feature.onboarding.login.OnboardingLoginSetupDependencies
|
||||
|
@ -37,6 +38,7 @@ import com.anytypeio.anytype.di.feature.settings.FilesStorageDependencies
|
|||
import com.anytypeio.anytype.di.feature.settings.LogoutWarningSubComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.MainSettingsSubComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.ProfileSubComponent
|
||||
import com.anytypeio.anytype.di.feature.settings.SpacesStorageDependencies
|
||||
import com.anytypeio.anytype.di.feature.spaces.CreateSpaceDependencies
|
||||
import com.anytypeio.anytype.di.feature.spaces.SelectSpaceDependencies
|
||||
import com.anytypeio.anytype.di.feature.spaces.SpaceSettingsDependencies
|
||||
|
@ -103,7 +105,10 @@ interface MainComponent :
|
|||
TemplateSelectDependencies,
|
||||
SelectSpaceDependencies,
|
||||
CreateSpaceDependencies,
|
||||
SpaceSettingsDependencies {
|
||||
SpaceSettingsDependencies,
|
||||
CreateObjectOfTypeDependencies,
|
||||
SpacesStorageDependencies
|
||||
{
|
||||
|
||||
fun inject(app: AndroidApplication)
|
||||
|
||||
|
@ -278,4 +283,14 @@ private abstract class ComponentDependenciesModule private constructor() {
|
|||
@IntoMap
|
||||
@ComponentDependenciesKey(SpaceSettingsDependencies::class)
|
||||
abstract fun provideSpaceSettingsDependencies(component: MainComponent): ComponentDependencies
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ComponentDependenciesKey(CreateObjectOfTypeDependencies::class)
|
||||
abstract fun provideCreateObjectOfTypeDependencies(component: MainComponent): ComponentDependencies
|
||||
|
||||
@Binds
|
||||
@IntoMap
|
||||
@ComponentDependenciesKey(SpacesStorageDependencies::class)
|
||||
abstract fun provideSpacesStorageDependencies(component: MainComponent): ComponentDependencies
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
package com.anytypeio.anytype.di.main
|
||||
|
||||
import com.anytypeio.anytype.di.main.ConfigModule.DEFAULT_APP_COROUTINE_SCOPE
|
||||
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.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfObjectTypes
|
||||
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
|
||||
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
|
||||
|
@ -11,10 +15,13 @@ import com.anytypeio.anytype.domain.search.ObjectTypesSubscriptionManager
|
|||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.search.RelationsSubscriptionManager
|
||||
import com.anytypeio.anytype.domain.search.SubscriptionEventChannel
|
||||
import com.anytypeio.anytype.domain.spaces.SpaceDeletedStatusWatcher
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import javax.inject.Named
|
||||
import javax.inject.Singleton
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@Module
|
||||
object SubscriptionsModule {
|
||||
|
@ -66,7 +73,7 @@ object SubscriptionsModule {
|
|||
subscription: RelationsSubscriptionContainer,
|
||||
spaceManager: SpaceManager
|
||||
): RelationsSubscriptionManager = RelationsSubscriptionManager(
|
||||
subscription = subscription,
|
||||
container = subscription,
|
||||
spaceManager = spaceManager
|
||||
)
|
||||
|
||||
|
@ -77,7 +84,26 @@ object SubscriptionsModule {
|
|||
subscription: ObjectTypesSubscriptionContainer,
|
||||
spaceManager: SpaceManager
|
||||
): ObjectTypesSubscriptionManager = ObjectTypesSubscriptionManager(
|
||||
subscription = subscription,
|
||||
container = subscription,
|
||||
spaceManager = spaceManager
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@Provides
|
||||
@Singleton
|
||||
fun spaceStatusWatcher(
|
||||
spaceManager: SpaceManager,
|
||||
dispatchers: AppCoroutineDispatchers,
|
||||
@Named(DEFAULT_APP_COROUTINE_SCOPE) scope: CoroutineScope,
|
||||
configStorage: ConfigStorage,
|
||||
container: StorelessSubscriptionContainer,
|
||||
logger: Logger
|
||||
) : SpaceDeletedStatusWatcher = SpaceDeletedStatusWatcher(
|
||||
spaceManager = spaceManager,
|
||||
dispatchers = dispatchers,
|
||||
configStorage = configStorage,
|
||||
scope = scope,
|
||||
container = container,
|
||||
logger = logger
|
||||
)
|
||||
}
|
|
@ -16,7 +16,7 @@ import com.anytypeio.anytype.ui.editor.EditorFragment
|
|||
import com.anytypeio.anytype.ui.editor.EditorModalFragment
|
||||
import com.anytypeio.anytype.ui.home.HomeScreenFragment
|
||||
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.settings.RemoteStorageFragment
|
||||
import com.anytypeio.anytype.ui.settings.RemoteFilesManageFragment
|
||||
import com.anytypeio.anytype.ui.templates.EditorTemplateFragment.Companion.TYPE_TEMPLATE_EDIT
|
||||
import com.anytypeio.anytype.ui.templates.EditorTemplateFragment.Companion.TYPE_TEMPLATE_SELECT
|
||||
import com.anytypeio.anytype.ui.templates.TemplateSelectFragment
|
||||
|
@ -305,9 +305,9 @@ class Navigator : AppNavigation {
|
|||
navController?.navigate(R.id.libraryFragment)
|
||||
}
|
||||
|
||||
override fun openRemoteStorageScreen(subscription: Id) {
|
||||
override fun openRemoteFilesManageScreen(subscription: Id) {
|
||||
navController?.navigate(R.id.remoteStorageFragment,
|
||||
bundleOf(RemoteStorageFragment.SUBSCRIPTION_KEY to subscription))
|
||||
bundleOf(RemoteFilesManageFragment.SUBSCRIPTION_KEY to subscription))
|
||||
}
|
||||
|
||||
override fun openTemplatesModal(typeId: Id) {
|
||||
|
|
|
@ -78,7 +78,7 @@ class NavigationRouter(
|
|||
|
||||
is AppNavigation.Command.OpenLibrary -> navigation.openLibrary()
|
||||
is AppNavigation.Command.MigrationErrorScreen -> navigation.migrationErrorScreen()
|
||||
is AppNavigation.Command.OpenRemoteStorageScreen -> navigation.openRemoteStorageScreen(
|
||||
is AppNavigation.Command.OpenRemoteFilesManageScreen -> navigation.openRemoteFilesManageScreen(
|
||||
command.subscription
|
||||
)
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.ScrollAndMove
|
|||
import com.anytypeio.anytype.core_ui.features.editor.scrollandmove.ScrollAndMoveTargetHighlighter
|
||||
import com.anytypeio.anytype.core_ui.menu.ObjectTypePopupMenu
|
||||
import com.anytypeio.anytype.core_ui.reactive.clicks
|
||||
import com.anytypeio.anytype.core_ui.reactive.longClicks
|
||||
import com.anytypeio.anytype.core_ui.tools.ClipboardInterceptor
|
||||
import com.anytypeio.anytype.core_ui.tools.EditorHeaderOverlayDetector
|
||||
import com.anytypeio.anytype.core_ui.tools.LastItemBottomOffsetDecorator
|
||||
|
@ -139,6 +140,7 @@ import com.anytypeio.anytype.ui.linking.OnLinkToAction
|
|||
import com.anytypeio.anytype.ui.moving.MoveToFragment
|
||||
import com.anytypeio.anytype.ui.moving.OnMoveToAction
|
||||
import com.anytypeio.anytype.ui.objects.appearance.ObjectAppearanceSettingFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.DraftObjectSelectTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectSelectTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.OnObjectSelectTypeAction
|
||||
|
@ -591,6 +593,26 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
|
|||
.onEach { vm.onAddNewDocumentClicked() }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
binding.bottomToolbar
|
||||
.addDocClicks()
|
||||
.onEach { vm.onAddNewDocumentClicked() }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
binding
|
||||
.bottomToolbar
|
||||
.binding
|
||||
.btnAddDoc
|
||||
.longClicks(withHaptic = true)
|
||||
.onEach {
|
||||
val dialog = CreateObjectOfTypeFragment().apply {
|
||||
onTypeSelected = {
|
||||
vm.onAddNewDocumentClicked(it)
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "editor-create-object-of-type-dialog")
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
binding.topToolbar.menu
|
||||
.clicks()
|
||||
.throttleFirst()
|
||||
|
|
|
@ -8,6 +8,7 @@ import androidx.core.os.bundleOf
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.analytics.BuildConfig
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_ui.features.objects.ObjectActionAdapter
|
||||
|
@ -18,16 +19,15 @@ import com.anytypeio.anytype.core_utils.ext.argOrNull
|
|||
import com.anytypeio.anytype.core_utils.ext.shareFile
|
||||
import com.anytypeio.anytype.core_utils.ext.throttleFirst
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
|
||||
import com.anytypeio.anytype.core_utils.ui.proceed
|
||||
import com.anytypeio.anytype.core_utils.ui.showActionableSnackBar
|
||||
import com.anytypeio.anytype.databinding.FragmentObjectMenuBinding
|
||||
import com.anytypeio.anytype.presentation.navigation.AppNavigation
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuOptionsProvider
|
||||
import com.anytypeio.anytype.presentation.objects.menu.ObjectMenuViewModelBase
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
import com.anytypeio.anytype.ui.editor.EditorModalFragment
|
||||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectFragment
|
||||
import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
|
||||
import com.anytypeio.anytype.ui.editor.layout.ObjectLayoutFragment
|
||||
|
@ -36,6 +36,7 @@ import com.anytypeio.anytype.ui.linking.BacklinkAction
|
|||
import com.anytypeio.anytype.ui.linking.BacklinkOrAddToObjectFragment
|
||||
import com.anytypeio.anytype.ui.moving.OnMoveToAction
|
||||
import com.anytypeio.anytype.ui.relations.ObjectRelationListFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
|
||||
abstract class ObjectMenuBaseFragment :
|
||||
BaseBottomSheetFragment<FragmentObjectMenuBinding>(),
|
||||
|
@ -79,6 +80,7 @@ abstract class ObjectMenuBaseFragment :
|
|||
click(binding.optionIcon) { vm.onIconClicked(ctx) }
|
||||
click(binding.optionRelations) { vm.onRelationsClicked() }
|
||||
click(binding.optionCover) { vm.onCoverClicked(ctx) }
|
||||
click(binding.debugGoroutines) { vm.onDiagnosticsGoroutinesClicked(ctx) }
|
||||
|
||||
proceed(vm.actions) { actionAdapter.submitList(it) }
|
||||
proceed(vm.toasts) { toast(it) }
|
||||
|
@ -86,6 +88,11 @@ abstract class ObjectMenuBaseFragment :
|
|||
proceed(vm.commands.throttleFirst()) { command -> execute(command) }
|
||||
proceed(vm.options) { options -> renderOptions(options) }
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
binding.debugGoroutines.visible()
|
||||
binding.debugGoroutinesDivider.visible()
|
||||
}
|
||||
|
||||
super.onStart()
|
||||
vm.onStart(
|
||||
ctx = ctx,
|
||||
|
@ -134,11 +141,24 @@ abstract class ObjectMenuBaseFragment :
|
|||
is ObjectMenuViewModelBase.Command.OpenSnackbar -> openSnackbar(command)
|
||||
is ObjectMenuViewModelBase.Command.ShareDebugTree -> shareFile(command.uri)
|
||||
is ObjectMenuViewModelBase.Command.OpenTemplate -> openTemplate(command)
|
||||
is ObjectMenuViewModelBase.Command.ShareDebugGoroutines -> {
|
||||
val snackbar = Snackbar.make(
|
||||
dialog?.window?.decorView!!,
|
||||
"Success, Path: ${command.path}",
|
||||
Snackbar.LENGTH_INDEFINITE
|
||||
)
|
||||
snackbar.setAction("Done") {
|
||||
snackbar.dismiss()
|
||||
}
|
||||
snackbar.anchorView = binding.anchor
|
||||
snackbar.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openTemplate(command: ObjectMenuViewModelBase.Command.OpenTemplate) {
|
||||
toast(getString(R.string.snackbar_template_add) + command.typeName)
|
||||
val msg = "${getString(R.string.snackbar_template_add)} ${command.typeName}"
|
||||
toast(msg)
|
||||
navigation().openModalTemplateEdit(
|
||||
template = command.templateId,
|
||||
templateTypeId = command.typeId,
|
||||
|
@ -175,7 +195,7 @@ abstract class ObjectMenuBaseFragment :
|
|||
ObjectRelationListFragment.ARG_TARGET to null,
|
||||
ObjectRelationListFragment.ARG_LOCKED to isLocked,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
|
||||
ObjectRelationListFragment.ARG_DATA_VIEW_FLOW to false
|
||||
ObjectRelationListFragment.ARG_SET_FLOW to false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -188,7 +208,7 @@ abstract class ObjectMenuBaseFragment :
|
|||
ObjectRelationListFragment.ARG_TARGET to null,
|
||||
ObjectRelationListFragment.ARG_LOCKED to isLocked,
|
||||
ObjectRelationListFragment.ARG_MODE to ObjectRelationListFragment.MODE_LIST,
|
||||
ObjectRelationListFragment.ARG_DATA_VIEW_FLOW to true
|
||||
ObjectRelationListFragment.ARG_SET_FLOW to true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -37,7 +37,9 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -50,6 +52,7 @@ import com.anytypeio.anytype.core_models.Id
|
|||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_ui.extensions.throttledClick
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleCombinedClickable
|
||||
import com.anytypeio.anytype.core_ui.views.UXBody
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.home.InteractionMode
|
||||
|
@ -95,6 +98,7 @@ fun HomeScreen(
|
|||
onLibraryClicked: () -> Unit,
|
||||
onOpenSpacesClicked: () -> Unit,
|
||||
onCreateNewObjectClicked: () -> Unit,
|
||||
onCreateNewObjectLongClicked: () -> Unit,
|
||||
onProfileClicked: () -> Unit,
|
||||
onObjectCheckboxClicked: (Id, Boolean) -> Unit,
|
||||
onSpaceWidgetClicked: () -> Unit,
|
||||
|
@ -158,6 +162,7 @@ fun HomeScreen(
|
|||
onSearchClicked = throttledClick(onSearchClicked),
|
||||
onCreateNewObjectClicked = throttledClick(onCreateNewObjectClicked),
|
||||
onProfileClicked = throttledClick(onProfileClicked),
|
||||
onCreateNewObjectLongClicked = onCreateNewObjectLongClicked,
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
|
@ -515,14 +520,17 @@ fun HomeScreenButton(
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun HomeScreenBottomToolbar(
|
||||
profileIcon: ProfileIconView,
|
||||
modifier: Modifier,
|
||||
onSearchClicked: () -> Unit,
|
||||
onCreateNewObjectClicked: () -> Unit,
|
||||
onCreateNewObjectLongClicked: () -> Unit,
|
||||
onProfileClicked: () -> Unit
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
Row(
|
||||
modifier = modifier
|
||||
.height(52.dp)
|
||||
|
@ -548,7 +556,16 @@ fun HomeScreenBottomToolbar(
|
|||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.fillMaxSize()
|
||||
.noRippleClickable { onCreateNewObjectClicked() }
|
||||
.noRippleCombinedClickable(
|
||||
onLongClicked = {
|
||||
onCreateNewObjectLongClicked().also {
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
onCreateNewObjectClicked()
|
||||
}
|
||||
)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_home_widget_plus),
|
||||
|
@ -585,7 +602,7 @@ fun HomeScreenBottomToolbar(
|
|||
contentDescription = "Custom image space icon",
|
||||
modifier = Modifier
|
||||
.size(24.dp)
|
||||
.clip(RoundedCornerShape(3.dp))
|
||||
.clip(CircleShape)
|
||||
.align(Alignment.Center),
|
||||
contentScale = ContentScale.Crop
|
||||
)
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.anytypeio.anytype.presentation.home.HomeScreenViewModel
|
|||
import com.anytypeio.anytype.presentation.home.HomeScreenViewModel.Navigation
|
||||
import com.anytypeio.anytype.presentation.widgets.DropDownMenuAction
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
import com.anytypeio.anytype.ui.widgets.SelectWidgetSourceFragment
|
||||
import com.anytypeio.anytype.ui.widgets.SelectWidgetTypeFragment
|
||||
|
@ -84,6 +85,17 @@ class HomeScreenFragment : BaseComposeFragment() {
|
|||
onCreateNewObjectClicked = throttledClick(
|
||||
onClick = { vm.onCreateNewObjectClicked() }
|
||||
),
|
||||
onCreateNewObjectLongClicked = throttledClick(
|
||||
onClick = {
|
||||
val dialog = CreateObjectOfTypeFragment().apply {
|
||||
onTypeSelected = {
|
||||
vm.onCreateNewObjectClicked(it)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "TEST")
|
||||
}
|
||||
),
|
||||
onProfileClicked = throttledClick(
|
||||
onClick = {
|
||||
runCatching {
|
||||
|
|
|
@ -24,6 +24,7 @@ import com.anytypeio.anytype.di.common.componentManager
|
|||
import com.anytypeio.anytype.presentation.library.LibraryViewModel
|
||||
import com.anytypeio.anytype.presentation.objects.ObjectIcon
|
||||
import com.anytypeio.anytype.ui.editor.EditorFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import com.anytypeio.anytype.ui.relations.REQUEST_KEY_MODIFY_RELATION
|
||||
import com.anytypeio.anytype.ui.relations.REQUEST_KEY_UNINSTALL_RELATION
|
||||
import com.anytypeio.anytype.ui.relations.REQUEST_UNINSTALL_RELATION_ARG_ID
|
||||
|
@ -63,11 +64,20 @@ class LibraryFragment : BaseComposeFragment() {
|
|||
setContent {
|
||||
MaterialTheme(typography = typography) {
|
||||
LibraryScreen(
|
||||
LibraryConfiguration(),
|
||||
vm
|
||||
) {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
configuration = LibraryConfiguration(),
|
||||
viewModel = vm,
|
||||
onBackPressed = {
|
||||
findNavController().popBackStack()
|
||||
},
|
||||
onCreateObjectLongClicked = {
|
||||
val dialog = CreateObjectOfTypeFragment().apply {
|
||||
onTypeSelected = {
|
||||
vm.onCreateObjectOfTypeClicked(it)
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "library-create-object-of-type-dialog")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,8 @@ import kotlinx.coroutines.FlowPreview
|
|||
fun LibraryScreen(
|
||||
configuration: LibraryConfiguration,
|
||||
viewModel: LibraryViewModel,
|
||||
onBackPressed: () -> Unit
|
||||
onBackPressed: () -> Unit,
|
||||
onCreateObjectLongClicked: () -> Unit
|
||||
) {
|
||||
|
||||
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
|
@ -67,7 +68,8 @@ fun LibraryScreen(
|
|||
Menu(
|
||||
viewModel,
|
||||
modifier = modifier,
|
||||
screenState = screenState
|
||||
screenState = screenState,
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked
|
||||
)
|
||||
}) {
|
||||
println(it)
|
||||
|
@ -105,7 +107,8 @@ fun LibraryScreen(
|
|||
fun Menu(
|
||||
viewModel: LibraryViewModel,
|
||||
modifier: Modifier = Modifier,
|
||||
screenState: MutableState<ScreenState>
|
||||
screenState: MutableState<ScreenState>,
|
||||
onCreateObjectLongClicked: () -> Unit = {}
|
||||
) {
|
||||
val isImeVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
|
||||
if (isImeVisible) return
|
||||
|
@ -115,12 +118,13 @@ fun Menu(
|
|||
if (screenState.value == ScreenState.SEARCH) {
|
||||
screenState.value = ScreenState.CONTENT
|
||||
} else {
|
||||
viewModel.eventStream(LibraryEvent.BottomMenu.Back())
|
||||
viewModel.eventStream(LibraryEvent.BottomMenu.Back)
|
||||
}
|
||||
},
|
||||
homeClick = { viewModel.eventStream(LibraryEvent.BottomMenu.Back()) },
|
||||
searchClick = { viewModel.eventStream(LibraryEvent.BottomMenu.Search()) },
|
||||
addDocClick = { viewModel.eventStream(LibraryEvent.BottomMenu.AddDoc()) },
|
||||
homeClick = { viewModel.eventStream(LibraryEvent.BottomMenu.Back) },
|
||||
searchClick = { viewModel.eventStream(LibraryEvent.BottomMenu.Search) },
|
||||
addDocClick = { viewModel.eventStream(LibraryEvent.BottomMenu.CreateObject) },
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -186,7 +186,6 @@ private fun SearchCancel(modifier: Modifier = Modifier, visible: Boolean = false
|
|||
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
private fun LibraryList(
|
||||
data: LibraryScreenState.Tabs.TabData,
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package com.anytypeio.anytype.ui.objects.creation
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.objects.CreateObjectOfTypeViewModel
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
import javax.inject.Inject
|
||||
|
||||
class CreateObjectOfTypeFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: CreateObjectOfTypeViewModel.Factory
|
||||
|
||||
private val vm by viewModels<CreateObjectOfTypeViewModel> { factory }
|
||||
|
||||
lateinit var onTypeSelected: (Key) -> Unit
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View = ComposeView(requireContext()).apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme(
|
||||
typography = typography
|
||||
) {
|
||||
CreateObjectOfTypeScreen(
|
||||
views = vm.views.collectAsStateWithLifecycle().value,
|
||||
onTypeClicked = {
|
||||
onTypeSelected.invoke(it)
|
||||
},
|
||||
onQueryChanged = vm::onQueryChanged,
|
||||
onFocused = { expand() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().createObjectOfTypeComponent.get().inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().createObjectOfTypeComponent.release()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,383 @@
|
|||
package com.anytypeio.anytype.ui.objects.creation
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.GridItemSpan
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.onFocusChanged
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_ui.extensions.throttledClick
|
||||
import com.anytypeio.anytype.core_ui.foundation.Dragger
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Medium
|
||||
import com.anytypeio.anytype.core_ui.views.Title2
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
import com.anytypeio.anytype.presentation.objects.SelectTypeView
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun PreviewScreen() {
|
||||
CreateObjectOfTypeScreen(
|
||||
onTypeClicked = {},
|
||||
views = emptyList(),
|
||||
onQueryChanged = {},
|
||||
onFocused = {}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CreateObjectOfTypeScreen(
|
||||
onTypeClicked: (Key) -> Unit,
|
||||
onQueryChanged: (String) -> Unit,
|
||||
onFocused: () -> Unit,
|
||||
views: List<SelectTypeView>
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())
|
||||
|
||||
) {
|
||||
Dragger(
|
||||
Modifier
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(vertical = 6.dp)
|
||||
)
|
||||
SearchField(
|
||||
onQueryChanged = onQueryChanged,
|
||||
onFocused = onFocused
|
||||
)
|
||||
ScreenContent(views, onTypeClicked)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ScreenContent(
|
||||
views: List<SelectTypeView>,
|
||||
onTypeClicked: (Key) -> Unit
|
||||
) {
|
||||
FlowRowContent(views, onTypeClicked)
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
private fun FlowRowContent(
|
||||
views: List<SelectTypeView>,
|
||||
onTypeClicked: (Key) -> Unit
|
||||
) {
|
||||
FlowRow(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 20.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
,
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
views.forEach { view ->
|
||||
when (view) {
|
||||
is SelectTypeView.Type -> {
|
||||
ObjectTypeItem(
|
||||
name = view.name,
|
||||
emoji = view.icon,
|
||||
onItemClicked = throttledClick(
|
||||
onClick = {
|
||||
onTypeClicked(view.typeKey)
|
||||
}
|
||||
),
|
||||
modifier = Modifier
|
||||
)
|
||||
}
|
||||
is SelectTypeView.Section.Groups -> {
|
||||
Section(
|
||||
title = stringResource(id = R.string.create_object_section_groups),
|
||||
)
|
||||
}
|
||||
is SelectTypeView.Section.Objects -> {
|
||||
Section(
|
||||
title = stringResource(id = R.string.create_object_section_objects)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
private fun LazyColumnContent(
|
||||
views: List<SelectTypeView>,
|
||||
onTypeClicked: (Key) -> Unit
|
||||
) {
|
||||
LazyVerticalGrid(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
columns = GridCells.Fixed(3),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
contentPadding = PaddingValues(
|
||||
start = 20.dp,
|
||||
end = 20.dp
|
||||
)
|
||||
) {
|
||||
views.forEach { view ->
|
||||
when (view) {
|
||||
is SelectTypeView.Section.Groups -> {
|
||||
item(
|
||||
key = view.javaClass.name,
|
||||
span = { GridItemSpan(maxLineSpan) }
|
||||
) {
|
||||
Section(
|
||||
title = stringResource(id = R.string.create_object_section_groups),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is SelectTypeView.Section.Objects -> {
|
||||
item(
|
||||
key = view.javaClass.name,
|
||||
span = { GridItemSpan(maxLineSpan) }
|
||||
) {
|
||||
Section(
|
||||
title = stringResource(id = R.string.create_object_section_objects)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
is SelectTypeView.Type -> {
|
||||
item(
|
||||
key = view.typeKey
|
||||
) {
|
||||
ObjectTypeItem(
|
||||
name = view.name,
|
||||
emoji = view.icon,
|
||||
onItemClicked = throttledClick(
|
||||
onClick = {
|
||||
onTypeClicked(view.typeKey)
|
||||
}
|
||||
),
|
||||
modifier = Modifier.animateItemPlacement()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ObjectTypeItem(
|
||||
modifier: Modifier,
|
||||
name: String,
|
||||
emoji: String,
|
||||
onItemClicked: () -> Unit
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
.height(48.dp)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = colorResource(id = R.color.shape_primary),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.clickable { onItemClicked() }
|
||||
,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier.width(14.dp)
|
||||
)
|
||||
val uri = Emojifier.safeUri(emoji)
|
||||
if (uri.isNotEmpty()) {
|
||||
Image(
|
||||
painter = rememberAsyncImagePainter(
|
||||
Emojifier.safeUri(emoji)
|
||||
),
|
||||
contentDescription = "Icon from URI",
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
Text(
|
||||
text = name,
|
||||
style = Title2,
|
||||
color = colorResource(id = R.color.text_primary),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier.padding(end = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun SearchField(
|
||||
onQueryChanged: (String) -> Unit,
|
||||
onFocused: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(48.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
val focusManager = LocalFocusManager.current
|
||||
val focusRequester = FocusRequester()
|
||||
val input = remember { mutableStateOf(String()) }
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth()
|
||||
.height(36.dp)
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(color = colorResource(id = R.color.shape_transparent))
|
||||
.align(Alignment.Center)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_search_18),
|
||||
contentDescription = "Search icon",
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterStart)
|
||||
.padding(start = 8.dp)
|
||||
)
|
||||
if (input.value.isNotEmpty()) {
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_clear_18),
|
||||
contentDescription = "Search icon",
|
||||
modifier = Modifier
|
||||
.align(Alignment.CenterEnd)
|
||||
.padding(end = 8.dp)
|
||||
.noRippleClickable {
|
||||
input.value = ""
|
||||
onQueryChanged("")
|
||||
}
|
||||
)
|
||||
}
|
||||
BasicTextField(
|
||||
value = input.value,
|
||||
onValueChange = {
|
||||
input.value = it
|
||||
onQueryChanged(it)
|
||||
},
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { focusManager.clearFocus() }
|
||||
),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 32.dp, end = 32.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
.focusRequester(focusRequester)
|
||||
.onFocusChanged { state ->
|
||||
if (state.isFocused)
|
||||
onFocused()
|
||||
}
|
||||
,
|
||||
maxLines = 1,
|
||||
singleLine = true,
|
||||
textStyle = BodyRegular.copy(
|
||||
color = colorResource(id = R.color.text_primary)
|
||||
),
|
||||
cursorBrush = SolidColor(
|
||||
colorResource(id = R.color.cursor_color)
|
||||
),
|
||||
decorationBox = @Composable { innerTextField ->
|
||||
TextFieldDefaults.OutlinedTextFieldDecorationBox(
|
||||
value = input.value,
|
||||
innerTextField = innerTextField,
|
||||
singleLine = true,
|
||||
enabled = true,
|
||||
placeholder = {
|
||||
Text(
|
||||
text = stringResource(R.string.search),
|
||||
style = BodyRegular
|
||||
)
|
||||
},
|
||||
colors = TextFieldDefaults.outlinedTextFieldColors(
|
||||
textColor = colorResource(id = R.color.text_primary),
|
||||
backgroundColor = Color.Transparent,
|
||||
disabledBorderColor = Color.Transparent,
|
||||
errorBorderColor = Color.Transparent,
|
||||
focusedBorderColor = Color.Transparent,
|
||||
unfocusedBorderColor = Color.Transparent,
|
||||
placeholderColor = colorResource(id = R.color.text_tertiary)
|
||||
),
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
visualTransformation = VisualTransformation.None,
|
||||
contentPadding = PaddingValues(
|
||||
start = 0.dp,
|
||||
top = 0.dp,
|
||||
end = 0.dp,
|
||||
bottom = 0.dp
|
||||
),
|
||||
border = {},
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Section(title: String) {
|
||||
Box(modifier = Modifier
|
||||
.height(52.dp)
|
||||
.fillMaxWidth()) {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(bottom = 8.dp)
|
||||
.align(Alignment.BottomStart),
|
||||
text = title,
|
||||
color = colorResource(id = R.color.text_secondary),
|
||||
style = Caption1Medium
|
||||
)
|
||||
}
|
||||
}
|
|
@ -75,14 +75,11 @@ import com.anytypeio.anytype.presentation.onboarding.OnboardingViewModel
|
|||
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingLoginSetupViewModel
|
||||
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingMnemonicLoginViewModel
|
||||
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingSetProfileNameViewModel
|
||||
import com.anytypeio.anytype.presentation.onboarding.signup.OnboardingVoidViewModel
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.AuthScreenWrapper
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signin.EnteringTheVoidScreen
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signin.RecoveryScreenWrapper
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signup.CreateSoulAnimWrapper
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signup.MnemonicPhraseScreenWrapper
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signup.SetProfileNameWrapper
|
||||
import com.anytypeio.anytype.ui.onboarding.screens.signup.VoidScreenWrapper
|
||||
import com.google.android.exoplayer2.ExoPlayer
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.Player
|
||||
|
@ -241,62 +238,6 @@ class OnboardingFragment : Fragment() {
|
|||
currentPage.value = OnboardingPage.RECOVERY
|
||||
Recovery(navController)
|
||||
}
|
||||
composable(
|
||||
route = OnboardingNavigation.void,
|
||||
enterTransition = {
|
||||
when (initialState.destination.route) {
|
||||
OnboardingNavigation.auth -> {
|
||||
fadeIn(tween(ANIMATION_LENGTH_FADE))
|
||||
}
|
||||
else -> {
|
||||
slideIntoContainer(Right, tween(ANIMATION_LENGTH_SLIDE))
|
||||
}
|
||||
}
|
||||
},
|
||||
exitTransition = {
|
||||
when (targetState.destination.route) {
|
||||
OnboardingNavigation.auth -> {
|
||||
fadeOut(tween(ANIMATION_LENGTH_FADE))
|
||||
}
|
||||
else -> {
|
||||
slideOutOfContainer(Left, tween(ANIMATION_LENGTH_SLIDE))
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
currentPage.value = OnboardingPage.VOID
|
||||
val component = componentManager().onboardingNewVoidComponent
|
||||
val vm = daggerViewModel { component.get().getViewModel() }
|
||||
|
||||
VoidScreenWrapper(
|
||||
contentPaddingTop = ContentPaddingTop(),
|
||||
onNextClicked = vm::onNextClicked,
|
||||
screenState = vm.state.collectAsState().value
|
||||
)
|
||||
|
||||
backButtonCallback.value = vm::onBackButtonPressed
|
||||
BackHandler { vm.onSystemBackPressed() }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
vm.navigation.collect { navigation ->
|
||||
when (navigation) {
|
||||
OnboardingVoidViewModel.Navigation.GoBack -> {
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
OnboardingVoidViewModel.Navigation.NavigateToMnemonic -> {
|
||||
navController.navigate(OnboardingNavigation.mnemonic)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
vm.toasts.collect { toast(it) }
|
||||
}
|
||||
DisposableEffect(Unit) {
|
||||
onDispose { component.release() }
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = OnboardingNavigation.mnemonic,
|
||||
enterTransition = {
|
||||
|
@ -325,7 +266,6 @@ class OnboardingFragment : Fragment() {
|
|||
// Do nothing
|
||||
}
|
||||
Mnemonic(
|
||||
contentPaddingTop = ContentPaddingTop(),
|
||||
mnemonicColorPalette = mnemonicColorPalette
|
||||
)
|
||||
BackHandler {
|
||||
|
@ -334,16 +274,11 @@ class OnboardingFragment : Fragment() {
|
|||
}
|
||||
composable(
|
||||
route = OnboardingNavigation.setProfileName,
|
||||
enterTransition = { slideIntoContainer(Left, tween(ANIMATION_LENGTH_SLIDE)) },
|
||||
enterTransition = {
|
||||
fadeIn(tween(ANIMATION_LENGTH_FADE))
|
||||
},
|
||||
exitTransition = {
|
||||
when (targetState.destination.route) {
|
||||
OnboardingNavigation.auth -> {
|
||||
fadeOut(tween(ANIMATION_LENGTH_FADE))
|
||||
}
|
||||
else -> {
|
||||
slideOutOfContainer(Left, tween(ANIMATION_LENGTH_SLIDE))
|
||||
}
|
||||
}
|
||||
fadeOut(tween(ANIMATION_LENGTH_FADE))
|
||||
}
|
||||
) {
|
||||
val focus = LocalFocusManager.current
|
||||
|
@ -352,31 +287,12 @@ class OnboardingFragment : Fragment() {
|
|||
focus.clearFocus(true)
|
||||
navController.popBackStack()
|
||||
}
|
||||
SetProfileName(
|
||||
navController = navController,
|
||||
contentPaddingTop = if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
|
||||
LocalConfiguration.current.screenHeightDp / 6
|
||||
else
|
||||
ContentPaddingTop()
|
||||
)
|
||||
SetProfileName(navController = navController)
|
||||
BackHandler {
|
||||
focus.clearFocus(true)
|
||||
navController.popBackStack()
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = OnboardingNavigation.createSoulAnim,
|
||||
enterTransition = {
|
||||
fadeIn(tween(ANIMATION_LENGTH_FADE))
|
||||
}
|
||||
) {
|
||||
currentPage.value = OnboardingPage.SOUL_CREATION_ANIM
|
||||
backButtonCallback.value = null
|
||||
CreateSoulAnimation(ContentPaddingTop())
|
||||
BackHandler {
|
||||
// Intercepting back-press event but doing nothing.
|
||||
}
|
||||
}
|
||||
composable(
|
||||
route = OnboardingNavigation.enterTheVoid,
|
||||
enterTransition = {
|
||||
|
@ -470,7 +386,6 @@ class OnboardingFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
@Composable
|
||||
private fun enterTheVoid(
|
||||
navController: NavHostController
|
||||
|
@ -511,25 +426,10 @@ class OnboardingFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated("To be deleted")
|
||||
@Composable
|
||||
private fun CreateSoulAnimation(contentPaddingTop: Int) {
|
||||
val component = componentManager().onboardingSoulCreationAnimComponent
|
||||
CreateSoulAnimWrapper(
|
||||
contentPaddingTop = contentPaddingTop,
|
||||
viewModel = daggerViewModel { component.get().getViewModel() },
|
||||
onAnimationComplete = {
|
||||
findNavController().navigate(R.id.action_openHome)
|
||||
}
|
||||
)
|
||||
DisposableEffect(Unit) {
|
||||
onDispose { component.release() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
private fun SetProfileName(navController: NavHostController, contentPaddingTop: Int) {
|
||||
private fun SetProfileName(
|
||||
navController: NavHostController
|
||||
) {
|
||||
val component = componentManager().onboardingSoulCreationComponent
|
||||
val vm = daggerViewModel { component.get().getViewModel() }
|
||||
|
||||
|
@ -537,7 +437,10 @@ class OnboardingFragment : Fragment() {
|
|||
val keyboardInsets = WindowInsets.ime
|
||||
val density = LocalDensity.current
|
||||
|
||||
SetProfileNameWrapper(vm, contentPaddingTop)
|
||||
SetProfileNameWrapper(
|
||||
viewModel = vm,
|
||||
onBackClicked = { navController.popBackStack() }
|
||||
)
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
vm.navigation.collect { command ->
|
||||
|
@ -552,7 +455,7 @@ class OnboardingFragment : Fragment() {
|
|||
)
|
||||
}
|
||||
is OnboardingSetProfileNameViewModel.Navigation.GoBack -> {
|
||||
TODO()
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -569,13 +472,11 @@ class OnboardingFragment : Fragment() {
|
|||
|
||||
@Composable
|
||||
private fun Mnemonic(
|
||||
contentPaddingTop: Int,
|
||||
mnemonicColorPalette: List<Color>
|
||||
) {
|
||||
val component = componentManager().onboardingMnemonicComponent
|
||||
val vm = daggerViewModel { component.get().getViewModel() }
|
||||
MnemonicPhraseScreenWrapper(
|
||||
contentPaddingTop = contentPaddingTop,
|
||||
viewModel = vm,
|
||||
onCheckLaterClicked = {
|
||||
findNavController().navigate(R.id.action_openHome)
|
||||
|
@ -713,6 +614,13 @@ class OnboardingFragment : Fragment() {
|
|||
}
|
||||
|
||||
fun releaseDependencies() {
|
||||
with(componentManager()) {
|
||||
onboardingComponent.release()
|
||||
onboardingMnemonicComponent.release()
|
||||
onboardingMnemonicLoginComponent.release()
|
||||
onboardingLoginSetupComponent.release()
|
||||
onboardingStartComponent.release()
|
||||
}
|
||||
componentManager().onboardingComponent.release()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,5 @@ object OnboardingNavigation {
|
|||
const val void = "void"
|
||||
const val mnemonic = "mnemonic"
|
||||
const val setProfileName = "createSoul"
|
||||
const val createSoulAnim = "createSoulAnim"
|
||||
const val enterTheVoid = "enterTheVoid"
|
||||
}
|
|
@ -4,7 +4,7 @@ enum class OnboardingPage(val num: Int, val visible: Boolean) {
|
|||
AUTH(0, false),
|
||||
VOID(1, true),
|
||||
MNEMONIC(2, false),
|
||||
SET_PROFILE_NAME(1, true),
|
||||
SET_PROFILE_NAME(1, false),
|
||||
SOUL_CREATION_ANIM(4, false),
|
||||
RECOVERY(5, false),
|
||||
ENTER_THE_VOID(6, false)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.ui.onboarding.screens
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -14,19 +15,18 @@ import androidx.compose.material.Text
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_ui.ColorButtonInversion
|
||||
import com.anytypeio.anytype.core_ui.OnBoardingTextPrimaryColor
|
||||
import com.anytypeio.anytype.core_ui.OnBoardingTextSecondaryColor
|
||||
import com.anytypeio.anytype.core_ui.OnboardingSubtitleColor
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
|
@ -35,7 +35,6 @@ import com.anytypeio.anytype.core_ui.views.HeadlineOnBoardingTitle
|
|||
import com.anytypeio.anytype.core_ui.views.OnBoardingButtonPrimary
|
||||
import com.anytypeio.anytype.core_ui.views.OnBoardingButtonSecondary
|
||||
import com.anytypeio.anytype.core_ui.views.TextOnBoardingDescription
|
||||
import com.anytypeio.anytype.core_ui.views.fontInterRegular
|
||||
import com.anytypeio.anytype.presentation.onboarding.OnboardingStartViewModel
|
||||
|
||||
@Preview
|
||||
|
@ -72,7 +71,7 @@ fun AuthScreen(
|
|||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center) {
|
||||
Title(modifier = Modifier)
|
||||
Title(modifier = Modifier.align(Alignment.CenterHorizontally))
|
||||
Subtitle(modifier = Modifier)
|
||||
Description()
|
||||
Spacer(modifier = Modifier.height(72.dp))
|
||||
|
@ -96,25 +95,11 @@ fun AuthScreen(
|
|||
|
||||
@Composable
|
||||
fun Title(modifier: Modifier = Modifier) {
|
||||
Box(
|
||||
Image(
|
||||
painter = painterResource(id = R.drawable.ic_the_everything_app) ,
|
||||
contentDescription = "Everything app logo",
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.onboarding_auth_title),
|
||||
textAlign = TextAlign.Center,
|
||||
style = HeadlineOnBoardingTitle
|
||||
.copy(
|
||||
color = OnBoardingTextPrimaryColor,
|
||||
fontFamily = fontInterRegular,
|
||||
fontSize = 40.sp,
|
||||
fontWeight = FontWeight.W300,
|
||||
lineHeight = 37.5.sp
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -196,7 +181,11 @@ fun TermsAndPolicy(
|
|||
)
|
||||
|
||||
pushStringAnnotation(tag = TermsOfUseTag, annotation = "")
|
||||
withStyle(style = SpanStyle(textDecoration = TextDecoration.Underline)) {
|
||||
withStyle(
|
||||
style = SpanStyle(
|
||||
color = Color(0xFF797976)
|
||||
)
|
||||
) {
|
||||
append(stringResource(id = R.string.onboarding_terms_and_policy_terms))
|
||||
}
|
||||
pop()
|
||||
|
@ -206,7 +195,11 @@ fun TermsAndPolicy(
|
|||
)
|
||||
|
||||
pushStringAnnotation(tag = PrivacyPolicyTag, annotation = "")
|
||||
withStyle(style = SpanStyle(textDecoration = TextDecoration.Underline)) {
|
||||
withStyle(
|
||||
style = SpanStyle(
|
||||
color = Color(0xFF797976)
|
||||
)
|
||||
) {
|
||||
append(stringResource(id = R.string.onboarding_terms_and_policy_privacy))
|
||||
}
|
||||
pop()
|
||||
|
@ -216,7 +209,7 @@ fun TermsAndPolicy(
|
|||
modifier = modifier.padding(vertical = 16.dp, horizontal = 58.dp),
|
||||
text = annotatedString,
|
||||
style = TextOnBoardingDescription
|
||||
.copy(color = OnBoardingTextSecondaryColor, textAlign = TextAlign.Center),
|
||||
.copy(color = Color(0xFF494843), textAlign = TextAlign.Center),
|
||||
onClick = {
|
||||
annotatedString.getStringAnnotations(TermsOfUseTag, it, it)
|
||||
.firstOrNull()?.let {
|
||||
|
|
|
@ -115,7 +115,7 @@ fun RecoveryScreen(
|
|||
}
|
||||
item {
|
||||
OnBoardingButtonPrimary(
|
||||
text = stringResource(id = R.string.next),
|
||||
text = stringResource(id = R.string.log_in),
|
||||
onClick = {
|
||||
onNextClicked.invoke(text.value).also {
|
||||
focus.clearFocus()
|
||||
|
|
|
@ -54,7 +54,6 @@ fun MnemonicPhraseScreenWrapper(
|
|||
viewModel: OnboardingMnemonicViewModel,
|
||||
onCheckLaterClicked: () -> Unit,
|
||||
copyMnemonicToClipboard: (String) -> Unit,
|
||||
contentPaddingTop: Int,
|
||||
vm: OnboardingMnemonicViewModel,
|
||||
mnemonicColorPalette: List<Color>
|
||||
) {
|
||||
|
@ -68,7 +67,6 @@ fun MnemonicPhraseScreenWrapper(
|
|||
}
|
||||
},
|
||||
copyMnemonicToClipboard = copyMnemonicToClipboard,
|
||||
contentPaddingTop = contentPaddingTop,
|
||||
mnemonicColorPalette = mnemonicColorPalette
|
||||
)
|
||||
}
|
||||
|
@ -84,7 +82,6 @@ fun PreviewMnemonicPhraseScreen() {
|
|||
reviewMnemonic = { /*TODO*/ },
|
||||
onCheckLaterClicked = { /*TODO*/ },
|
||||
copyMnemonicToClipboard = {},
|
||||
contentPaddingTop = 0,
|
||||
mnemonicColorPalette = emptyList()
|
||||
)
|
||||
}
|
||||
|
@ -96,7 +93,6 @@ fun MnemonicPhraseScreen(
|
|||
reviewMnemonic: () -> Unit,
|
||||
onCheckLaterClicked: () -> Unit,
|
||||
copyMnemonicToClipboard: (String) -> Unit,
|
||||
contentPaddingTop: Int,
|
||||
mnemonicColorPalette: List<Color>
|
||||
) {
|
||||
val showWhatIsRecoveryPhraseDialog = remember { mutableStateOf(false) }
|
||||
|
@ -107,7 +103,7 @@ fun MnemonicPhraseScreen(
|
|||
.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.Top
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(contentPaddingTop.dp))
|
||||
Spacer(modifier = Modifier.height(148.dp))
|
||||
MnemonicTitle()
|
||||
MnemonicDescription()
|
||||
ReadMoreButton(showWhatIsRecoveryPhraseDialog)
|
||||
|
@ -153,7 +149,7 @@ private fun ReadMoreButton(showWhatIsRecoveryPhraseDialog: MutableState<Boolean>
|
|||
Text(
|
||||
text = stringResource(id = R.string.onboarding_mnemonic_read_more),
|
||||
style = BodyRegular.copy(
|
||||
color = Color.White
|
||||
color = Color(0xFFDBDAD4)
|
||||
),
|
||||
modifier = Modifier.align(Alignment.Center)
|
||||
)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
package com.anytypeio.anytype.ui.onboarding.screens.signup
|
||||
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.ime
|
||||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
|
@ -23,8 +21,8 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -33,6 +31,7 @@ import com.anytypeio.anytype.R
|
|||
import com.anytypeio.anytype.core_models.Name
|
||||
import com.anytypeio.anytype.core_ui.OnBoardingTextPrimaryColor
|
||||
import com.anytypeio.anytype.core_ui.OnBoardingTextSecondaryColor
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonSize
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineHeading
|
||||
import com.anytypeio.anytype.core_ui.views.HeadlineOnBoardingDescription
|
||||
|
@ -42,74 +41,60 @@ import com.anytypeio.anytype.ui.onboarding.OnboardingInput
|
|||
|
||||
|
||||
@Composable
|
||||
fun SetProfileNameWrapper(viewModel: OnboardingSetProfileNameViewModel, contentPaddingTop: Int) {
|
||||
fun SetProfileNameWrapper(
|
||||
viewModel: OnboardingSetProfileNameViewModel,
|
||||
onBackClicked: () -> Unit,
|
||||
) {
|
||||
SetProfileNameScreen(
|
||||
contentPaddingTop = contentPaddingTop,
|
||||
onNextClicked = viewModel::onNextClicked,
|
||||
isLoading = viewModel.state
|
||||
.collectAsStateWithLifecycle()
|
||||
.value is OnboardingSetProfileNameViewModel.ScreenState.Loading
|
||||
.value is OnboardingSetProfileNameViewModel.ScreenState.Loading,
|
||||
onBackClicked = onBackClicked
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SetProfileNameScreen(
|
||||
contentPaddingTop: Int,
|
||||
onNextClicked: (Name) -> Unit,
|
||||
onBackClicked: () -> Unit,
|
||||
isLoading: Boolean
|
||||
) {
|
||||
val text = remember { mutableStateOf("") }
|
||||
val isKeyboardVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
|
||||
val animatedSpacerHeight = animateDpAsState(
|
||||
targetValue = if (isKeyboardVisible)
|
||||
contentPaddingTop.dp - 72.dp
|
||||
else
|
||||
contentPaddingTop.dp
|
||||
)
|
||||
val focus = LocalFocusManager.current
|
||||
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
) {
|
||||
item {
|
||||
Spacer(
|
||||
modifier = Modifier.height(animatedSpacerHeight.value)
|
||||
)
|
||||
}
|
||||
item {
|
||||
SetProfileNameTitle(modifier = Modifier.padding(bottom = 12.dp))
|
||||
}
|
||||
item {
|
||||
SetProfileNameDescription()
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
item {
|
||||
SetProfileNameInput(
|
||||
text = text,
|
||||
onKeyboardActionDoneClicked = { onNextClicked(text.value) }
|
||||
)
|
||||
}
|
||||
item {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
Column {
|
||||
Spacer(
|
||||
modifier = Modifier.height(148.dp)
|
||||
)
|
||||
SetProfileNameTitle(modifier = Modifier.padding(bottom = 12.dp))
|
||||
SetProfileNameDescription()
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SetProfileNameInput(
|
||||
text = text,
|
||||
onKeyboardActionDoneClicked = { onNextClicked(text.value) }
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
Image(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopStart)
|
||||
.padding(top = 16.dp, start = 9.dp)
|
||||
.noRippleClickable {
|
||||
focus.clearFocus()
|
||||
onBackClicked()
|
||||
},
|
||||
painter = painterResource(id = R.drawable.ic_back_onboarding_32),
|
||||
contentDescription = "Back button"
|
||||
)
|
||||
SetProfileNameNextButton(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.imePadding()
|
||||
.padding(start = 20.dp, end = 20.dp)
|
||||
.then(
|
||||
if (isKeyboardVisible)
|
||||
Modifier.padding(bottom = 0.dp)
|
||||
else
|
||||
Modifier.padding(bottom = 13.dp)
|
||||
)
|
||||
.padding(start = 20.dp, end = 20.dp, bottom = 12.dp)
|
||||
,
|
||||
onNextClicked = onNextClicked,
|
||||
text = text,
|
||||
|
@ -137,6 +122,7 @@ fun SetProfileNameTitle(modifier: Modifier) {
|
|||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun SetProfileNameInput(
|
||||
text: MutableState<String>,
|
||||
|
@ -149,9 +135,7 @@ fun SetProfileNameInput(
|
|||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val focus = LocalFocusManager.current
|
||||
val isKeyboardVisible = WindowInsets.ime.getBottom(LocalDensity.current) > 0
|
||||
val focusRequester = FocusRequester()
|
||||
|
||||
OnboardingInput(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -167,11 +151,6 @@ fun SetProfileNameInput(
|
|||
}
|
||||
)
|
||||
)
|
||||
|
||||
if (!isKeyboardVisible) {
|
||||
focus.clearFocus()
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
|
|
|
@ -12,7 +12,9 @@ import androidx.compose.foundation.layout.padding
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
@ -47,7 +49,9 @@ fun PreviewWhatIsRecoveryPhraseScreen() {
|
|||
@Composable
|
||||
fun WhatIsRecoveryPhraseScreen() {
|
||||
Column(
|
||||
modifier = Modifier.padding(horizontal = 24.dp)
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 24.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
|
@ -152,19 +156,33 @@ fun WhatIsRecoveryPhraseScreen() {
|
|||
.fillMaxWidth()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(15.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.onboarding_how_to_save_my_phrase_2),
|
||||
color = Color.White,
|
||||
style = BodyCalloutRegular,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
Row(Modifier.padding(horizontal = 16.dp)) {
|
||||
Text(
|
||||
text = " • ",
|
||||
color = Color.White,
|
||||
style = BodyRegular
|
||||
)
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.onboarding_how_to_save_my_phrase_2),
|
||||
color = Color.White,
|
||||
style = BodyCalloutRegular
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.onboarding_how_to_save_my_phrase_3),
|
||||
color = Color.White,
|
||||
style = BodyCalloutRegular,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
Row(Modifier.padding(horizontal = 16.dp)) {
|
||||
Text(
|
||||
text = " • ",
|
||||
color = Color.White,
|
||||
style = BodyRegular
|
||||
)
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.onboarding_how_to_save_my_phrase_3),
|
||||
color = Color.White,
|
||||
style = BodyCalloutRegular
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import androidx.lifecycle.repeatOnLifecycle
|
|||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.features.relations.ObjectTypeAddAdapter
|
||||
import com.anytypeio.anytype.core_ui.reactive.textChanges
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.visible
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
|
||||
|
@ -47,6 +48,14 @@ class LimitObjectTypeFragment : BaseBottomSheetFragment<FragmentObjectTypeChange
|
|||
}
|
||||
lifecycleScope.launch {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
launch {
|
||||
binding
|
||||
.searchObjectTypeInput
|
||||
.textChanges()
|
||||
.collect {
|
||||
vm.onSearchInputChanged(it.toString())
|
||||
}
|
||||
}
|
||||
launch {
|
||||
vm.views.collectLatest {
|
||||
objectTypeAdapter.submitList(it)
|
||||
|
|
|
@ -51,7 +51,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
private val target: String? get() = argStringOrNull(ARG_TARGET)
|
||||
private val mode: Int get() = argInt(ARG_MODE)
|
||||
private val isLocked: Boolean get() = arg(ARG_LOCKED)
|
||||
private val isDataViewFLow: Boolean get() = arg(ARG_DATA_VIEW_FLOW)
|
||||
private val isSetFlow: Boolean get() = arg(ARG_SET_FLOW)
|
||||
|
||||
private val docRelationAdapter by lazy {
|
||||
DocumentRelationAdapter(
|
||||
|
@ -97,7 +97,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
if (!isLocked) {
|
||||
RelationAddToObjectFragment.new(
|
||||
ctx = ctx,
|
||||
isSetOrCollection = isDataViewFLow
|
||||
isSetOrCollection = isSetFlow
|
||||
).showChildFragment()
|
||||
} else {
|
||||
toast(getString(R.string.unlock_your_object_to_add_new_relation))
|
||||
|
@ -114,7 +114,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
relationKey = command.relationKey,
|
||||
objectId = command.target,
|
||||
isLocked = command.isLocked,
|
||||
flow = if (isDataViewFLow)
|
||||
flow = if (isSetFlow)
|
||||
RelationTextValueFragment.FLOW_DATAVIEW
|
||||
else
|
||||
RelationTextValueFragment.FLOW_DEFAULT
|
||||
|
@ -126,7 +126,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
ctx = ctx,
|
||||
relationKey = command.relationKey,
|
||||
objectId = command.target,
|
||||
flow = if (isDataViewFLow) {
|
||||
flow = if (isSetFlow) {
|
||||
RelationDateValueFragment.FLOW_SET_OR_COLLECTION
|
||||
} else {
|
||||
RelationDateValueFragment.FLOW_DEFAULT
|
||||
|
@ -134,8 +134,8 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
is Command.EditRelationValue -> {
|
||||
if (isDataViewFLow) {
|
||||
is Command.EditTagFileObjectRelationValue -> {
|
||||
if (isSetFlow) {
|
||||
val fr = RelationValueDVFragment().apply {
|
||||
arguments = RelationValueDVFragment.args(
|
||||
ctx = command.ctx,
|
||||
|
@ -167,7 +167,7 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
dismiss()
|
||||
}
|
||||
is Command.EditStatusRelationValue -> {
|
||||
if (isDataViewFLow) {
|
||||
if (isSetFlow) {
|
||||
val fr = RelationValueDVFragment().apply {
|
||||
arguments = RelationValueDVFragment.args(
|
||||
ctx = command.ctx,
|
||||
|
@ -272,16 +272,16 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
if (isDataViewFLow) {
|
||||
componentManager().dataViewRelationListComponent.get(ctx).inject(this)
|
||||
if (isSetFlow) {
|
||||
componentManager().objectSetRelationListComponent.get(ctx).inject(this)
|
||||
} else {
|
||||
componentManager().objectRelationListComponent.get(ctx).inject(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
if (isDataViewFLow) {
|
||||
componentManager().dataViewRelationListComponent.release(ctx)
|
||||
if (isSetFlow) {
|
||||
componentManager().objectSetRelationListComponent.release(ctx)
|
||||
} else {
|
||||
componentManager().objectRelationListComponent.release(ctx)
|
||||
}
|
||||
|
@ -294,20 +294,25 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
inflater, container, false
|
||||
)
|
||||
|
||||
/**
|
||||
* This screen should be started from Objects with Editor Layouts
|
||||
* or from objects with Set or Collection Layouts
|
||||
* @param isSetFlow - true if started from Set or Collection
|
||||
*/
|
||||
companion object {
|
||||
fun new(
|
||||
ctx: String,
|
||||
target: String?,
|
||||
mode: Int,
|
||||
locked: Boolean = false,
|
||||
isDataViewFlow: Boolean = false,
|
||||
isSetFlow: Boolean = false,
|
||||
) = ObjectRelationListFragment().apply {
|
||||
arguments = bundleOf(
|
||||
ARG_CTX to ctx,
|
||||
ARG_TARGET to target,
|
||||
ARG_MODE to mode,
|
||||
ARG_LOCKED to locked,
|
||||
ARG_DATA_VIEW_FLOW to isDataViewFlow
|
||||
ARG_SET_FLOW to isSetFlow
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -317,6 +322,6 @@ open class ObjectRelationListFragment : BaseBottomSheetFragment<FragmentRelation
|
|||
const val ARG_LOCKED = "arg.document-relation.locked"
|
||||
const val MODE_ADD = 1
|
||||
const val MODE_LIST = 2
|
||||
const val ARG_DATA_VIEW_FLOW = "arg.document-relation.data-view-flow"
|
||||
const val ARG_SET_FLOW = "arg.document-relation.set-flow"
|
||||
}
|
||||
}
|
|
@ -119,12 +119,17 @@ open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationV
|
|||
}
|
||||
|
||||
private fun showAddObjectScreen() {
|
||||
val flow = if (isIntrinsic) {
|
||||
AddObjectRelationFragment.FLOW_OBJECT_SET
|
||||
} else {
|
||||
AddObjectRelationFragment.FLOW_DATAVIEW
|
||||
}
|
||||
val fr = AddObjectRelationFragment.new(
|
||||
ctx = ctx,
|
||||
relationKey = relationKey,
|
||||
objectId = target,
|
||||
types = types,
|
||||
flow = AddObjectRelationFragment.FLOW_DATAVIEW
|
||||
flow = flow
|
||||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
|
@ -133,7 +138,8 @@ open class RelationValueDVFragment : RelationValueBaseFragment<FragmentRelationV
|
|||
val fr = AddOptionsRelationDVFragment.new(
|
||||
ctx = ctx,
|
||||
target = target,
|
||||
relationKey = relationKey
|
||||
relationKey = relationKey,
|
||||
isIntrinsic = isIntrinsic
|
||||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
|
|
|
@ -139,7 +139,8 @@ class RelationValueFragment : RelationValueBaseFragment<FragmentRelationValueBin
|
|||
ctx = ctx,
|
||||
relationKey = relationKey,
|
||||
objectId = target,
|
||||
types = types
|
||||
types = types,
|
||||
flow = AddObjectRelationFragment.FLOW_OBJECT
|
||||
)
|
||||
fr.showChildFragment()
|
||||
}
|
||||
|
|
|
@ -164,18 +164,31 @@ class AddObjectRelationFragment : BaseDialogFragment<FragmentRelationObjectValue
|
|||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
if (flow == FLOW_DEFAULT) {
|
||||
componentManager().addObjectRelationObjectValueComponent.get(ctx).inject(this)
|
||||
} else {
|
||||
componentManager().addObjectSetObjectRelationObjectValueComponent.get(ctx).inject(this)
|
||||
when (flow) {
|
||||
FLOW_OBJECT -> {
|
||||
componentManager().addObjectRelationObjectValueComponent.get(ctx).inject(this)
|
||||
}
|
||||
FLOW_OBJECT_SET -> {
|
||||
componentManager().addObjectSetObjectRelationObjectValueComponent.get(ctx)
|
||||
.inject(this)
|
||||
}
|
||||
FLOW_DATAVIEW -> {
|
||||
componentManager().addDataViewRelationObjectValueComponent.get(ctx).inject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
if (flow == FLOW_DEFAULT) {
|
||||
componentManager().addObjectRelationObjectValueComponent.release(ctx)
|
||||
} else {
|
||||
componentManager().addObjectSetObjectRelationObjectValueComponent.release(ctx)
|
||||
when (flow) {
|
||||
FLOW_OBJECT -> {
|
||||
componentManager().addObjectRelationObjectValueComponent.release(ctx)
|
||||
}
|
||||
FLOW_OBJECT_SET -> {
|
||||
componentManager().addObjectSetObjectRelationObjectValueComponent.release(ctx)
|
||||
}
|
||||
FLOW_DATAVIEW -> {
|
||||
componentManager().addDataViewRelationObjectValueComponent.release(ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,7 +206,7 @@ class AddObjectRelationFragment : BaseDialogFragment<FragmentRelationObjectValue
|
|||
objectId: Id,
|
||||
relationKey: Key,
|
||||
types: List<Id>,
|
||||
flow: Int = FLOW_DEFAULT
|
||||
flow: Int
|
||||
) = AddObjectRelationFragment().apply {
|
||||
arguments = bundleOf(
|
||||
CONTEXT_ID to ctx,
|
||||
|
@ -209,8 +222,9 @@ class AddObjectRelationFragment : BaseDialogFragment<FragmentRelationObjectValue
|
|||
const val OBJECT_ID = "arg.relation.add.object.object.id"
|
||||
const val TARGET_TYPES = "arg.relation.add.object.target_types"
|
||||
const val FLOW_KEY = "arg.relation.add.object.flow"
|
||||
const val FLOW_DEFAULT = 0
|
||||
const val FLOW_DATAVIEW = 1
|
||||
const val FLOW_OBJECT = 1
|
||||
const val FLOW_OBJECT_SET = 2
|
||||
const val FLOW_DATAVIEW = 3
|
||||
}
|
||||
|
||||
interface ObjectValueAddReceiver {
|
||||
|
|
|
@ -4,6 +4,7 @@ import androidx.core.os.bundleOf
|
|||
import androidx.fragment.app.viewModels
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_utils.ext.argOrNull
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.relations.RelationValueView
|
||||
import com.anytypeio.anytype.presentation.relations.add.AddOptionsRelationDVViewModel
|
||||
|
@ -15,6 +16,8 @@ open class AddOptionsRelationDVFragment : BaseAddOptionsRelationFragment() {
|
|||
lateinit var factory: AddOptionsRelationDVViewModel.Factory
|
||||
override val vm: AddOptionsRelationDVViewModel by viewModels { factory }
|
||||
|
||||
private val isIntrinsic: Boolean get() = argOrNull<Boolean>(IS_INTRINSIC_KEY) ?: false
|
||||
|
||||
override fun onStatusClicked(status: RelationValueView.Option.Status) {
|
||||
vm.onAddObjectSetStatusClicked(
|
||||
obj = target,
|
||||
|
@ -41,24 +44,36 @@ open class AddOptionsRelationDVFragment : BaseAddOptionsRelationFragment() {
|
|||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().addObjectSetObjectRelationValueComponent.get(ctx).inject(this)
|
||||
if (isIntrinsic) {
|
||||
componentManager().addObjectSetObjectRelationValueComponent.get(ctx).inject(this)
|
||||
} else {
|
||||
componentManager().addDataViewObjectRelationValueComponent.get(ctx).inject(this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().addObjectSetObjectRelationValueComponent.release(ctx)
|
||||
if (isIntrinsic) {
|
||||
componentManager().addObjectSetObjectRelationValueComponent.release(ctx)
|
||||
} else {
|
||||
componentManager().addDataViewObjectRelationValueComponent.release(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun new(
|
||||
ctx: Id,
|
||||
target: Id,
|
||||
relationKey: Key
|
||||
relationKey: Key,
|
||||
isIntrinsic: Boolean
|
||||
) = AddOptionsRelationDVFragment().apply {
|
||||
arguments = bundleOf(
|
||||
CTX_KEY to ctx,
|
||||
TARGET_KEY to target,
|
||||
RELATION_KEY to relationKey
|
||||
RELATION_KEY to relationKey,
|
||||
IS_INTRINSIC_KEY to isIntrinsic
|
||||
)
|
||||
}
|
||||
|
||||
private const val IS_INTRINSIC_KEY = "args.relations.edit-value.is-intrinsic"
|
||||
}
|
||||
}
|
|
@ -48,6 +48,7 @@ import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridAdapter
|
|||
import com.anytypeio.anytype.core_ui.features.dataview.ViewerGridHeaderAdapter
|
||||
import com.anytypeio.anytype.core_ui.reactive.clicks
|
||||
import com.anytypeio.anytype.core_ui.reactive.editorActionEvents
|
||||
import com.anytypeio.anytype.core_ui.reactive.longClicks
|
||||
import com.anytypeio.anytype.core_ui.reactive.touches
|
||||
import com.anytypeio.anytype.core_ui.tools.DefaultTextWatcher
|
||||
import com.anytypeio.anytype.core_ui.views.ButtonPrimarySmallIcon
|
||||
|
@ -94,6 +95,7 @@ import com.anytypeio.anytype.ui.editor.cover.SelectCoverObjectSetFragment
|
|||
import com.anytypeio.anytype.ui.editor.modals.IconPickerFragmentBase
|
||||
import com.anytypeio.anytype.ui.editor.sheets.ObjectMenuBaseFragment
|
||||
import com.anytypeio.anytype.ui.objects.BaseObjectTypeChangeFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.DataViewSelectSourceFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.EmptyDataViewSelectSourceFragment
|
||||
import com.anytypeio.anytype.ui.objects.types.pickers.ObjectSelectTypeFragment
|
||||
|
@ -290,6 +292,21 @@ open class ObjectSetFragment :
|
|||
subscribe(
|
||||
binding.bottomToolbar.addDocClicks().throttleFirst()
|
||||
) { vm.onAddNewDocumentClicked() }
|
||||
|
||||
binding
|
||||
.bottomToolbar
|
||||
.binding
|
||||
.btnAddDoc
|
||||
.longClicks(withHaptic = true)
|
||||
.onEach {
|
||||
val dialog = CreateObjectOfTypeFragment().apply {
|
||||
onTypeSelected = {
|
||||
vm.onAddNewDocumentClicked(it)
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "set-create-object-of-type-dialog")
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
with(binding.paginatorToolbar) {
|
||||
|
|
|
@ -12,16 +12,9 @@ import androidx.lifecycle.Lifecycle
|
|||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
|
||||
import com.anytypeio.anytype.core_utils.ext.arg
|
||||
import com.anytypeio.anytype.core_utils.ext.safeNavigate
|
||||
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_utils.intents.SystemAction
|
||||
import com.anytypeio.anytype.core_utils.intents.proceedWithAction
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.core_utils.ui.proceed
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
|
@ -30,14 +23,11 @@ import com.anytypeio.anytype.presentation.settings.FilesStorageViewModel.Event
|
|||
import com.anytypeio.anytype.ui.auth.account.DeleteAccountWarning
|
||||
import com.anytypeio.anytype.ui.dashboard.ClearCacheAlertFragment
|
||||
import com.anytypeio.anytype.ui_settings.fstorage.LocalStorageScreen
|
||||
import com.anytypeio.anytype.ui_settings.fstorage.RemoteStorageScreen
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FilesStorageFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
private val isRemote get() = arg<Boolean>(ARG_STORAGE_TYPE)
|
||||
|
||||
@Inject
|
||||
lateinit var factory: FilesStorageViewModel.Factory
|
||||
|
||||
|
@ -55,19 +45,11 @@ class FilesStorageFragment : BaseBottomSheetComposeFragment() {
|
|||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme(typography = typography) {
|
||||
if (isRemote) {
|
||||
RemoteStorageScreen(
|
||||
data = vm.state.collectAsStateWithLifecycle().value,
|
||||
onManageFilesClicked = { throttle { vm.event(Event.OnManageFilesClicked) } },
|
||||
onGetMoreSpaceClicked = { throttle { vm.event(Event.OnGetMoreSpaceClicked) } },
|
||||
)
|
||||
} else {
|
||||
LocalStorageScreen(
|
||||
data = vm.state.collectAsStateWithLifecycle().value,
|
||||
onOffloadFilesClicked = { throttle { vm.event(Event.OnOffloadFilesClicked) } },
|
||||
onDeleteAccountClicked = { proceedWithAccountDeletion() }
|
||||
)
|
||||
}
|
||||
LocalStorageScreen(
|
||||
data = vm.state.collectAsStateWithLifecycle().value,
|
||||
onOffloadFilesClicked = { throttle { vm.event(Event.OnOffloadFilesClicked) } },
|
||||
onDeleteAccountClicked = { proceedWithAccountDeletion() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,20 +83,6 @@ class FilesStorageFragment : BaseBottomSheetComposeFragment() {
|
|||
private fun processCommands(command: FilesStorageViewModel.Command) {
|
||||
when (command) {
|
||||
FilesStorageViewModel.Command.OpenOffloadFilesScreen -> showClearCacheDialog()
|
||||
is FilesStorageViewModel.Command.OpenRemoteStorageScreen -> openRemoteStorageScreen(
|
||||
subscription = command.subscription
|
||||
)
|
||||
is FilesStorageViewModel.Command.SendGetMoreSpaceEmail -> {
|
||||
proceedWithAction(
|
||||
SystemAction.MailTo(
|
||||
generateSupportMail(
|
||||
account = command.account,
|
||||
limit = command.limit,
|
||||
name = command.name
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,14 +92,6 @@ class FilesStorageFragment : BaseBottomSheetComposeFragment() {
|
|||
dialog.show(childFragmentManager, null)
|
||||
}
|
||||
|
||||
private fun openRemoteStorageScreen(subscription: String) {
|
||||
findNavController().safeNavigate(
|
||||
R.id.filesStorageScreen,
|
||||
R.id.remoteStorageFragment,
|
||||
bundleOf(RemoteStorageFragment.SUBSCRIPTION_KEY to subscription)
|
||||
)
|
||||
}
|
||||
|
||||
private fun proceedWithAccountDeletion() {
|
||||
vm.proceedWithAccountDeletion()
|
||||
val dialog = DeleteAccountWarning()
|
||||
|
@ -142,18 +102,6 @@ class FilesStorageFragment : BaseBottomSheetComposeFragment() {
|
|||
dialog.show(childFragmentManager, null)
|
||||
}
|
||||
|
||||
private fun generateSupportMail(
|
||||
account: Id,
|
||||
name: String,
|
||||
limit: String,
|
||||
|
||||
) : String {
|
||||
val bodyString = resources.getString(R.string.mail_more_space_body, limit, account, name)
|
||||
return "storage@anytype.io" +
|
||||
"?subject=Get%20more%20storage,%20account%20$account" +
|
||||
"&body=$bodyString"
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().filesStorageComponent.get().inject(this)
|
||||
}
|
||||
|
|
|
@ -97,11 +97,7 @@ class ProfileSettingsFragment : BaseBottomSheetComposeFragment() {
|
|||
),
|
||||
onDataManagementClicked = throttledClick(
|
||||
onClick = {
|
||||
findNavController()
|
||||
.navigate(
|
||||
R.id.filesStorageScreen,
|
||||
FilesStorageFragment.args(isRemote = false)
|
||||
)
|
||||
findNavController().navigate(R.id.filesStorageScreen)
|
||||
}
|
||||
),
|
||||
onAboutClicked = throttledClick(
|
||||
|
|
|
@ -21,10 +21,10 @@ import com.anytypeio.anytype.presentation.widgets.collection.Subscription
|
|||
import com.anytypeio.anytype.presentation.widgets.collection.SubscriptionMapper
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
import com.anytypeio.anytype.ui.dashboard.DeleteAlertFragment
|
||||
import com.anytypeio.anytype.ui.settings.remote.RemoteStorageScreen
|
||||
import com.anytypeio.anytype.ui.settings.remote.RemoteFilesManageScreen
|
||||
import javax.inject.Inject
|
||||
|
||||
class RemoteStorageFragment : BaseBottomSheetComposeFragment() {
|
||||
class RemoteFilesManageFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: CollectionViewModel.Factory
|
||||
|
@ -47,7 +47,7 @@ class RemoteStorageFragment : BaseBottomSheetComposeFragment() {
|
|||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme(typography = typography) {
|
||||
RemoteStorageScreen(vm = vm)
|
||||
RemoteFilesManageScreen(vm = vm)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package com.anytypeio.anytype.ui.settings
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import com.anytypeio.anytype.R
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_utils.ext.toast
|
||||
import com.anytypeio.anytype.core_ui.common.ComposeDialogView
|
||||
import com.anytypeio.anytype.core_utils.ext.safeNavigate
|
||||
import com.anytypeio.anytype.core_utils.ext.setupBottomSheetBehavior
|
||||
import com.anytypeio.anytype.core_utils.intents.SystemAction
|
||||
import com.anytypeio.anytype.core_utils.intents.proceedWithAction
|
||||
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
|
||||
import com.anytypeio.anytype.core_utils.ui.proceed
|
||||
import com.anytypeio.anytype.di.common.componentManager
|
||||
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModelFactory
|
||||
import com.anytypeio.anytype.presentation.settings.SpacesStorageViewModel
|
||||
import com.anytypeio.anytype.ui_settings.space.SpaceStorageScreen
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SpacesStorageFragment : BaseBottomSheetComposeFragment() {
|
||||
|
||||
@Inject
|
||||
lateinit var factory: SpacesStorageViewModelFactory
|
||||
|
||||
private val vm by viewModels<SpacesStorageViewModel> { factory }
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
return ComposeDialogView(
|
||||
context = requireContext(),
|
||||
dialog = requireDialog()
|
||||
).apply {
|
||||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
MaterialTheme(typography = typography) {
|
||||
SpaceStorageScreen(
|
||||
data = vm.viewState.collectAsStateWithLifecycle().value,
|
||||
onManageFilesClicked = { throttle { vm.event(SpacesStorageViewModel.Event.OnManageFilesClicked) } },
|
||||
onGetMoreSpaceClicked = { throttle { vm.event(SpacesStorageViewModel.Event.OnGetMoreSpaceClicked) } },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupBottomSheetBehavior(PADDING_TOP)
|
||||
collectCommands()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
proceed(vm.toasts) { toast(it) }
|
||||
vm.onStart()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
vm.onStop()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun collectCommands() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
vm.commands.collect { command -> processCommands(command) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processCommands(command: SpacesStorageViewModel.Command) {
|
||||
when (command) {
|
||||
is SpacesStorageViewModel.Command.OpenRemoteFilesManageScreen -> {
|
||||
openRemoteStorageScreen(
|
||||
subscription = command.subscription
|
||||
)
|
||||
}
|
||||
is SpacesStorageViewModel.Command.SendGetMoreSpaceEmail -> {
|
||||
proceedWithAction(
|
||||
SystemAction.MailTo(
|
||||
generateSupportMail(
|
||||
account = command.account,
|
||||
limit = command.limit,
|
||||
name = command.name
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun openRemoteStorageScreen(subscription: String) {
|
||||
findNavController().safeNavigate(
|
||||
R.id.spacesStorageScreen,
|
||||
R.id.remoteStorageFragment,
|
||||
bundleOf(RemoteFilesManageFragment.SUBSCRIPTION_KEY to subscription)
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateSupportMail(
|
||||
account: Id,
|
||||
name: String,
|
||||
limit: String,
|
||||
|
||||
): String {
|
||||
val bodyString = resources.getString(R.string.mail_more_space_body, limit, account, name)
|
||||
return "storage@anytype.io" +
|
||||
"?subject=Get%20more%20storage,%20account%20$account" +
|
||||
"&body=$bodyString"
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().spacesStorageComponent.get().inject(this)
|
||||
}
|
||||
|
||||
override fun releaseDependencies() {
|
||||
componentManager().spacesStorageComponent.release()
|
||||
}
|
||||
}
|
||||
|
||||
private const val PADDING_TOP = 54
|
|
@ -53,7 +53,7 @@ import kotlinx.coroutines.launch
|
|||
|
||||
@ExperimentalMaterialApi
|
||||
@Composable
|
||||
fun RemoteStorageScreen(vm: CollectionViewModel) {
|
||||
fun RemoteFilesManageScreen(vm: CollectionViewModel) {
|
||||
val uiState by vm.uiState.collectAsStateWithLifecycle()
|
||||
val showFileAlert by vm.openFileDeleteAlert.collectAsStateWithLifecycle()
|
||||
|
|
@ -48,7 +48,6 @@ import com.anytypeio.anytype.di.common.componentManager
|
|||
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel
|
||||
import com.anytypeio.anytype.presentation.spaces.SpaceSettingsViewModel.Command
|
||||
import com.anytypeio.anytype.presentation.util.downloader.UriFileProvider
|
||||
import com.anytypeio.anytype.ui.settings.FilesStorageFragment
|
||||
import com.anytypeio.anytype.ui.settings.typography
|
||||
import com.anytypeio.anytype.ui.spaces.DeleteSpaceWarning
|
||||
import com.anytypeio.anytype.ui.spaces.Section
|
||||
|
@ -82,21 +81,21 @@ class SpaceSettingsFragment : BaseBottomSheetComposeFragment() {
|
|||
spaceData = vm.spaceViewState.collectAsStateWithLifecycle().value,
|
||||
onDeleteSpaceClicked = throttledClick(
|
||||
onClick = {
|
||||
vm.onDeleteSpaceClicked()
|
||||
val dialog = DeleteSpaceWarning.new()
|
||||
dialog.onDeletionAccepted = {
|
||||
dialog.dismiss()
|
||||
vm.onDeleteSpaceClicked()
|
||||
vm.onDeleteSpaceAcceptedClicked()
|
||||
}
|
||||
dialog.onDeletionCancelled = {
|
||||
vm.onDeleteSpaceWarningCancelled()
|
||||
}
|
||||
dialog.show(childFragmentManager, null)
|
||||
}
|
||||
),
|
||||
onFileStorageClick = throttledClick(
|
||||
onClick = {
|
||||
findNavController()
|
||||
.navigate(
|
||||
R.id.filesStorageScreen,
|
||||
FilesStorageFragment.args(isRemote = true)
|
||||
)
|
||||
findNavController().navigate(R.id.spacesStorageScreen)
|
||||
}
|
||||
),
|
||||
onPersonalizationClicked = throttledClick(
|
||||
|
|
|
@ -6,13 +6,15 @@ import androidx.compose.foundation.layout.Box
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.TextFieldDefaults
|
||||
|
@ -60,36 +62,44 @@ fun CreateSpaceScreen(
|
|||
val input = remember {
|
||||
mutableStateOf("")
|
||||
}
|
||||
Column(modifier = Modifier.fillMaxHeight()) {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
Dragger(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 6.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.align(Alignment.TopCenter)
|
||||
)
|
||||
Header()
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SpaceIcon(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
spaceIconView = spaceIconView,
|
||||
onSpaceIconClicked = onSpaceIconClicked
|
||||
)
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
SpaceNameInput(input = input)
|
||||
Divider()
|
||||
Section(title = stringResource(id = R.string.type))
|
||||
TypeOfSpace(spaceType = PRIVATE_SPACE_TYPE)
|
||||
Divider()
|
||||
Section(title = stringResource(id = R.string.create_space_start_with))
|
||||
UseCase()
|
||||
Divider()
|
||||
Box(modifier = Modifier.weight(1.0f)) {
|
||||
CreateSpaceButton(
|
||||
onCreate = onCreate,
|
||||
input = input,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
isLoading = isLoading
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Header()
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SpaceIcon(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
spaceIconView = spaceIconView,
|
||||
onSpaceIconClicked = onSpaceIconClicked
|
||||
)
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
SpaceNameInput(input = input)
|
||||
Divider()
|
||||
Section(title = stringResource(id = R.string.type))
|
||||
TypeOfSpace(spaceType = PRIVATE_SPACE_TYPE)
|
||||
Divider()
|
||||
Section(title = stringResource(id = R.string.create_space_start_with))
|
||||
UseCase()
|
||||
Divider()
|
||||
Spacer(modifier = Modifier.height(78.dp))
|
||||
}
|
||||
CreateSpaceButton(
|
||||
onCreate = onCreate,
|
||||
input = input,
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
isLoading = isLoading
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class DeleteSpaceWarning : BaseBottomSheetComposeFragment() {
|
|||
private val name: String get() = arg(ARG_NAME)
|
||||
|
||||
var onDeletionAccepted: () -> Unit = {}
|
||||
var onDeletionCancelled: () -> Unit = {}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
@ -35,7 +36,10 @@ class DeleteSpaceWarning : BaseBottomSheetComposeFragment() {
|
|||
cancelButtonText = stringResource(R.string.back),
|
||||
title = stringResource(R.string.delete_space_title),
|
||||
subtitle = stringResource(R.string.delete_space_subtitle),
|
||||
onNegativeClick = { dismiss() },
|
||||
onNegativeClick = {
|
||||
onDeletionCancelled()
|
||||
dismiss()
|
||||
},
|
||||
onPositiveClick = { onDeletionAccepted() },
|
||||
isInProgress = false
|
||||
)
|
||||
|
|
|
@ -88,6 +88,16 @@ class SelectSpaceFragment : BaseBottomSheetComposeFragment() {
|
|||
expand()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
vm.onStart()
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
vm.onStop()
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun injectDependencies() {
|
||||
componentManager().selectSpaceComponent.get().inject(this)
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import androidx.compose.ui.res.colorResource
|
|||
import androidx.compose.ui.res.painterResource
|
||||
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 androidx.compose.ui.unit.sp
|
||||
import coil.compose.rememberAsyncImagePainter
|
||||
|
@ -150,17 +151,22 @@ private fun SelectSpaceSpaceItem(
|
|||
SpaceImageBlock(
|
||||
icon = item.view.icon,
|
||||
onSpaceIconClick = { onSpaceClicked(item.view) },
|
||||
gradientBackground = colorResource(id = R.color.default_gradient_background)
|
||||
gradientBackground = colorResource(id = R.color.default_gradient_background),
|
||||
gradientCornerRadius = 4.dp
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(10.dp))
|
||||
Text(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(horizontal = 8.dp)
|
||||
,
|
||||
text = item.view.name.orEmpty().ifEmpty { stringResource(id = R.string.untitled) },
|
||||
textAlign = TextAlign.Center,
|
||||
style = Caption1Medium,
|
||||
color = Color.White,
|
||||
maxLines = 1
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import com.anytypeio.anytype.domain.workspace.SpaceManager
|
|||
import com.anytypeio.anytype.presentation.util.Dispatcher
|
||||
import com.anytypeio.anytype.presentation.widgets.WidgetDispatchEvent
|
||||
import com.anytypeio.anytype.presentation.widgets.collection.CollectionViewModel
|
||||
import com.anytypeio.anytype.ui.settings.RemoteStorageFragment
|
||||
import com.anytypeio.anytype.ui.settings.RemoteFilesManageFragment
|
||||
import dagger.Binds
|
||||
import dagger.Component
|
||||
import dagger.Module
|
||||
|
@ -53,7 +53,7 @@ interface CollectionComponent {
|
|||
}
|
||||
|
||||
fun inject(fragment: CollectionFragment)
|
||||
fun inject(fragment: RemoteStorageFragment)
|
||||
fun inject(fragment: RemoteFilesManageFragment)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.anytypeio.anytype.presentation.widgets.collection.Subscription
|
|||
import com.anytypeio.anytype.presentation.widgets.collection.SubscriptionMapper
|
||||
import com.anytypeio.anytype.ui.base.navigation
|
||||
import com.anytypeio.anytype.ui.dashboard.DeleteAlertFragment
|
||||
import com.anytypeio.anytype.ui.objects.creation.CreateObjectOfTypeFragment
|
||||
import javax.inject.Inject
|
||||
|
||||
class CollectionFragment : BaseComposeFragment() {
|
||||
|
@ -48,7 +49,17 @@ class CollectionFragment : BaseComposeFragment() {
|
|||
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
|
||||
setContent {
|
||||
DefaultTheme {
|
||||
CollectionScreen(vm)
|
||||
CollectionScreen(
|
||||
vm = vm,
|
||||
onCreateObjectLongClicked = {
|
||||
val dialog = CreateObjectOfTypeFragment().apply {
|
||||
onTypeSelected = {
|
||||
vm.onAddClicked(it)
|
||||
}
|
||||
}
|
||||
dialog.show(childFragmentManager, "fullscreen-widget-create-object-of-type-dialog")
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,7 +109,11 @@ import org.burnoutcrew.reorderable.reorderable
|
|||
|
||||
@SuppressLint("UnusedMaterialScaffoldPaddingParameter")
|
||||
@Composable
|
||||
fun ScreenContent(vm: CollectionViewModel, uiState: CollectionUiState) {
|
||||
fun ScreenContent(
|
||||
vm: CollectionViewModel,
|
||||
uiState: CollectionUiState,
|
||||
onCreateObjectLongClicked: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
Modifier.background(color = colorResource(R.color.background_primary))
|
||||
)
|
||||
|
@ -130,6 +134,7 @@ fun ScreenContent(vm: CollectionViewModel, uiState: CollectionUiState) {
|
|||
homeClick = { vm.onHomeClicked() },
|
||||
searchClick = { vm.onSearchClicked() },
|
||||
addDocClick = { vm.onAddClicked() },
|
||||
onCreateObjectLongClicked = onCreateObjectLongClicked
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -532,7 +537,10 @@ fun CollectionItem(
|
|||
|
||||
@ExperimentalMaterialApi
|
||||
@Composable
|
||||
fun CollectionScreen(vm: CollectionViewModel) {
|
||||
fun CollectionScreen(
|
||||
vm: CollectionViewModel,
|
||||
onCreateObjectLongClicked: () -> Unit
|
||||
) {
|
||||
|
||||
val uiState by vm.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
|
@ -550,7 +558,7 @@ fun CollectionScreen(vm: CollectionViewModel) {
|
|||
sheetContent = { BlockWidget(localDensity, vm, state) },
|
||||
sheetPeekHeight = 0.dp
|
||||
) {
|
||||
ScreenContent(vm, state)
|
||||
ScreenContent(vm, state, onCreateObjectLongClicked)
|
||||
|
||||
LaunchedEffect(state) {
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -45,6 +47,7 @@ fun BinWidgetCard(
|
|||
val isHeaderMenuExpanded = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val haptic = LocalHapticFeedback.current
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -62,6 +65,7 @@ fun BinWidgetCard(
|
|||
},
|
||||
onLongClick = {
|
||||
isCardMenuExpanded.value = !isCardMenuExpanded.value
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
|
|
|
@ -17,6 +17,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -35,6 +37,7 @@ fun LibraryWidgetCard(
|
|||
onClick: () -> Unit,
|
||||
onDropDownMenuAction: (DropDownMenuAction) -> Unit,
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
val isCardMenuExpanded = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
|
@ -58,6 +61,7 @@ fun LibraryWidgetCard(
|
|||
},
|
||||
onLongClick = {
|
||||
isCardMenuExpanded.value = !isCardMenuExpanded.value
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
|
|
|
@ -20,6 +20,8 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -48,6 +50,7 @@ fun LinkWidgetCard(
|
|||
val isHeaderMenuExpanded = remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val haptic = LocalHapticFeedback.current
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -67,6 +70,7 @@ fun LinkWidgetCard(
|
|||
onClick = { onWidgetSourceClicked(item.source) },
|
||||
onLongClick = {
|
||||
isCardMenuExpanded.value = !isCardMenuExpanded.value
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
|
|
|
@ -51,7 +51,8 @@ fun SpaceWidgetCard(
|
|||
onSpaceIconClick = {},
|
||||
mainSize = 40.dp,
|
||||
gradientSize = 24.dp,
|
||||
emojiSize = 24.dp
|
||||
emojiSize = 24.dp,
|
||||
gradientCornerRadius = 2.dp
|
||||
)
|
||||
}
|
||||
Text(
|
||||
|
|
|
@ -33,6 +33,8 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.rotate
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
@ -245,6 +247,7 @@ fun WidgetHeader(
|
|||
isExpanded: Boolean = false,
|
||||
isInEditMode: Boolean = true
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
Box(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
@ -272,6 +275,7 @@ fun WidgetHeader(
|
|||
onClick = onWidgetHeaderClicked,
|
||||
onLongClick = {
|
||||
isCardMenuExpanded.value = !isCardMenuExpanded.value
|
||||
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||
},
|
||||
indication = null,
|
||||
interactionSource = remember { MutableInteractionSource() }
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<View
|
||||
android:id="@+id/dragger"
|
||||
|
@ -160,6 +161,32 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/objectDiagnostics" />
|
||||
|
||||
<com.anytypeio.anytype.core_ui.widgets.ObjectMenuItemWidget
|
||||
android:id="@+id/debugGoroutines"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@drawable/default_ripple"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_object_menu_debug_goroutines"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/objectDiagnosticsDivider"
|
||||
app:subtitle="Command Debug.StackGoroutines"
|
||||
app:title="Debug Goroutines"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<View
|
||||
android:id="@+id/debugGoroutinesDivider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_marginTop="21dp"
|
||||
android:visibility="gone"
|
||||
android:background="@color/shape_primary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/debugGoroutines" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/rvContainer"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -167,7 +194,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/objectDiagnosticsDivider">
|
||||
app:layout_constraintTop_toBottomOf="@+id/debugGoroutinesDivider">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_gravity="center_vertical"
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
|
||||
<dialog
|
||||
android:id="@+id/remoteStorageFragment"
|
||||
android:name="com.anytypeio.anytype.ui.settings.RemoteStorageFragment"/>
|
||||
android:name="com.anytypeio.anytype.ui.settings.RemoteFilesManageFragment"/>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/selectWidgetTypeScreen"
|
||||
|
@ -237,6 +237,12 @@
|
|||
android:label="Files-Storage-Screen">
|
||||
</dialog>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/spacesStorageScreen"
|
||||
android:name="com.anytypeio.anytype.ui.settings.SpacesStorageFragment"
|
||||
android:label="Spaces-Storage-Screen">
|
||||
</dialog>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/aboutAppScreen"
|
||||
android:name="com.anytypeio.anytype.ui.settings.AboutAppFragment" />
|
||||
|
|
|
@ -363,17 +363,17 @@ Do the computation of an expensive paragraph of text on a background thread:
|
|||
<string name="onboarding_terms_and_policy_terms">Terms\u00A0of\u00A0Use</string>
|
||||
<string name="onboarding_terms_and_policy_infix">" and "</string>
|
||||
<string name="onboarding_terms_and_policy_privacy">Privacy\u00A0Policy</string>
|
||||
<string name="onboarding_join_button_text">Create new account</string>
|
||||
<string name="onboarding_join_button_text">Create New Account</string>
|
||||
<string name="onboarding_log_in_button_text">Login</string>
|
||||
<string name="onboarding_invite_code_title">Enter your invite code</string>
|
||||
<string name="onboarding_invite_code_description">If you don\'t have one just go to anytype.io\nand sign up to the waiting list.</string>
|
||||
<string name="onboarding_void_title">This is your Void</string>
|
||||
<string name="onboarding_void_description">It is an encrypted location for everything you create. Everything is stored on your device, and backed up to the distributed network.</string>
|
||||
<string name="onboarding_mnemonic_title">Save your recovery phrase</string>
|
||||
<string name="onboarding_mnemonic_title">Save your Recovery Phrase</string>
|
||||
<string name="onboarding_mnemonic_description">It’s a novel way of authentication that gives you full ownership over your account and data.</string>
|
||||
<string name="onboarding_mnemonic_show_key">Show Recovery Phrase</string>
|
||||
<string name="onboarding_mnemonic_key_saved">Go to the app</string>
|
||||
<string name="onboarding_mnemonic_skip">Check later</string>
|
||||
<string name="onboarding_mnemonic_skip">Skip</string>
|
||||
<string name="onboarding_mnemonic_copy">Copy to clipboard</string>
|
||||
<string name="onboarding_set_your_name_title">Choose your name</string>
|
||||
<string name="onboarding_soul_creation_description">This is how you will appear in the app</string>
|
||||
|
@ -413,20 +413,23 @@ Do the computation of an expensive paragraph of text on a background thread:
|
|||
<string name="onboarding_mnemonic_read_more">Read more</string>
|
||||
<string name="onboarding_mnemonic_additional_info">You can find Recovery Phrase later in\nAnytype settings</string>
|
||||
<string name="onboqrding_what_is_recovery_phrase">What is Recovery Phrase?</string>
|
||||
<string name="onboarding_recovery_phrase_description">Recovery Phrase is 12 random words from which your account is magically generated on this device.</string>
|
||||
<string name="onboarding_recovery_phrase_description_2">"Who knows combination of these words – owns the account. "</string>
|
||||
<string name="onboarding_recovery_phrase_description_3">Now, you are the only person in the world who can access it.</string>
|
||||
<string name="onboarding_recovery_phrase_description_4">That is why it is essential to keep Recovery Phrase secure! You own - you responsible!</string>
|
||||
<string name="onboarding_how_to_save_my_phrase">How to save my phrase?</string>
|
||||
<string name="onboarding_recovery_phrase_description">Recovery Phrase is a random combination of 12 words from which your account is magically generated on this device.</string>
|
||||
<string name="onboarding_recovery_phrase_description_2">Whomever knows Recovery Phrase, owns the account. </string>
|
||||
<string name="onboarding_recovery_phrase_description_3">At this moment, you are the only person in the world who knows it.</string>
|
||||
<string name="onboarding_recovery_phrase_description_4">That\'s why it\'s essential to keep Recovery Phrase safe. As the sole owner, nobody can help you if it\'s lost.</string>
|
||||
<string name="onboarding_how_to_save_my_phrase">How to save my Phrase?</string>
|
||||
<string name="onboarding_how_to_save_my_phrase_2">The easiest way to store your Recovery Phrase is to save it in your password manager.</string>
|
||||
<string name="onboarding_how_to_save_my_phrase_3">The most secure way is to write it down on paper and keep it offline, in a safe and secure place.</string>
|
||||
<string name="anytype_update_alert_description">Some of your data was managed in a newer version of Anytype. Please update the app to work with all your docs and the latest features.</string>
|
||||
<string name="anytype_update_alert_title">It’s time to update</string>
|
||||
<string name="anytype_update_alert_description">This object was modified in a newer version of Anytype. Please update the app to open it on this device.</string>
|
||||
<string name="anytype_update_alert_title">Update Your App</string>
|
||||
<string name="download_anytype_url">https://download.anytype.io</string>
|
||||
|
||||
<string name="space_type_personal">Personal</string>
|
||||
<string name="space_type_private">Private</string>
|
||||
<string name="space_type_personal">Personal Space</string>
|
||||
<string name="space_type_private">Private Space</string>
|
||||
<string name="space_type_unknown">Unknown</string>
|
||||
<string name="create_space_start_with">Start with</string>
|
||||
<string name="create_object_section_groups">Groups</string>
|
||||
<string name="create_object_section_objects">Objects</string>
|
||||
<string name="log_in">Log In</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
const val NO_VALUE = ""
|
||||
const val NO_VALUE = ""
|
||||
const val EMPTY_QUERY = ""
|
|
@ -1,7 +1,10 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
sealed class FileLimitsEvent {
|
||||
data class SpaceUsage(val bytesUsage: Long) : FileLimitsEvent()
|
||||
data class SpaceUsage(
|
||||
val space: Id,
|
||||
val bytesUsage: Long
|
||||
) : FileLimitsEvent()
|
||||
data class LocalUsage(val bytesUsage: Long) : FileLimitsEvent()
|
||||
data class FileLimitReached(
|
||||
val spaceId: String,
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package com.anytypeio.anytype.core_models
|
||||
|
||||
data class NodeUsageInfo(
|
||||
val nodeUsage: NodeUsage = NodeUsage.empty(),
|
||||
val spaces: List<SpaceUsage> = emptyList()
|
||||
)
|
||||
|
||||
data class NodeUsage(
|
||||
var filesCount: Long?,
|
||||
var cidsCount: Long?,
|
||||
var bytesUsage: Long?,
|
||||
var bytesLeft: Long?,
|
||||
var bytesLimit: Long?,
|
||||
var localBytesUsage: Long?
|
||||
) {
|
||||
companion object {
|
||||
fun empty() = NodeUsage(
|
||||
filesCount = null,
|
||||
cidsCount = null,
|
||||
bytesUsage = null,
|
||||
bytesLeft = null,
|
||||
bytesLimit = null,
|
||||
localBytesUsage = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class SpaceUsage(
|
||||
var space: Id,
|
||||
var filesCount: Long,
|
||||
var cidsCount: Long,
|
||||
var bytesUsage: Long
|
||||
)
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.core_models
|
|||
import com.anytypeio.anytype.core_models.Relations.RELATION_FORMAT_OBJECT_TYPES
|
||||
import com.anytypeio.anytype.core_models.ext.typeOf
|
||||
import com.anytypeio.anytype.core_models.restrictions.ObjectRestriction
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
|
||||
/**
|
||||
* Wrapper for easily parsing object's relations when object is represented as an untyped structure.
|
||||
|
@ -134,6 +135,8 @@ sealed class ObjectWrapper {
|
|||
val isValid get() = map.containsKey(Relations.ID)
|
||||
|
||||
val notDeletedNorArchived get() = (isDeleted != true && isArchived != true)
|
||||
|
||||
val targetSpaceId: String? by default
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -239,11 +242,19 @@ sealed class ObjectWrapper {
|
|||
val color: String = relationOptionColor.orEmpty()
|
||||
}
|
||||
|
||||
data class Workspace(override val map: Struct) : ObjectWrapper() {
|
||||
data class SpaceView(override val map: Struct) : ObjectWrapper() {
|
||||
private val default = map.withDefault { null }
|
||||
val id: Id by default
|
||||
val name: String? by default
|
||||
val spaceId: String? by default
|
||||
val targetSpaceId: String? by default
|
||||
val spaceAccountStatus: SpaceStatus
|
||||
get() {
|
||||
val code = getValue<Double?>(Relations.SPACE_ACCOUNT_STATUS)
|
||||
return SpaceStatus
|
||||
.values()
|
||||
.firstOrNull { it.code == code?.toInt() }
|
||||
?: SpaceStatus.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> getValue(relation: Key): T? {
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
package com.anytypeio.anytype.core_models.restrictions
|
||||
|
||||
enum class SpaceStatus(val code: Number) {
|
||||
DELETED(7),
|
||||
OK(2)
|
||||
UNKNOWN(0),
|
||||
LOADING(1),
|
||||
OK(2),
|
||||
MISSING(3),
|
||||
ERROR(4),
|
||||
REMOTE_WAITING_DELETION(5),
|
||||
REMOTE_DELETED(6),
|
||||
SPACE_DELETED(7),
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package com.anytypeio.anytype.core_ui.foundation
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.Indication
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.combinedClickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
|
@ -23,7 +25,21 @@ fun Modifier.noRippleClickable(
|
|||
enabled = enabled,
|
||||
onClickLabel = onClickLabel,
|
||||
role = role,
|
||||
onClick = onClick
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
@Composable
|
||||
fun Modifier.noRippleCombinedClickable(
|
||||
enabled: Boolean = true,
|
||||
onLongClicked: () -> Unit,
|
||||
onClick: () -> Unit,
|
||||
) = combinedClickable(
|
||||
interactionSource = remember { MutableInteractionSource() },
|
||||
indication = null,
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
onLongClick = onLongClicked
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -11,12 +11,15 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.anytypeio.anytype.core_ui.R
|
||||
import com.anytypeio.anytype.core_ui.foundation.components.BottomNavigationDefaults.Height
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
|
||||
import com.anytypeio.anytype.core_ui.foundation.noRippleCombinedClickable
|
||||
|
||||
|
||||
@Composable
|
||||
|
@ -26,6 +29,7 @@ fun BottomNavigationMenu(
|
|||
homeClick: () -> Unit = {},
|
||||
searchClick: () -> Unit = {},
|
||||
addDocClick: () -> Unit = {},
|
||||
onCreateObjectLongClicked: () -> Unit = {}
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier
|
||||
|
@ -42,21 +46,33 @@ fun BottomNavigationMenu(
|
|||
MenuItem(BottomNavigationItem.BACK.res, onClick = backClick)
|
||||
MenuItem(BottomNavigationItem.HOME.res, onClick = homeClick)
|
||||
MenuItem(BottomNavigationItem.SEARCH.res, onClick = searchClick)
|
||||
MenuItem(BottomNavigationItem.ADD_DOC.res, onClick = addDocClick)
|
||||
MenuItem(
|
||||
BottomNavigationItem.ADD_DOC.res,
|
||||
onClick = addDocClick,
|
||||
onLongClick = onCreateObjectLongClicked
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MenuItem(
|
||||
@DrawableRes res: Int,
|
||||
onClick: () -> Unit = {}
|
||||
onClick: () -> Unit = {},
|
||||
onLongClick: () -> Unit = {},
|
||||
) {
|
||||
val haptic = LocalHapticFeedback.current
|
||||
Image(
|
||||
painter = painterResource(id = res),
|
||||
contentDescription = "",
|
||||
modifier = Modifier.noRippleClickable {
|
||||
onClick.invoke()
|
||||
}
|
||||
modifier = Modifier.noRippleCombinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClicked = {
|
||||
haptic.performHapticFeedback(
|
||||
HapticFeedbackType.LongPress
|
||||
)
|
||||
onLongClick()
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.anytypeio.anytype.core_ui.reactive
|
|||
import android.os.Looper
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.widget.EditText
|
||||
|
@ -27,6 +28,19 @@ fun View.clicks(): Flow<Unit> = callbackFlow {
|
|||
awaitClose { setOnClickListener(null) }
|
||||
}.conflate()
|
||||
|
||||
fun View.longClicks(withHaptic: Boolean = false): Flow<Unit> = callbackFlow {
|
||||
checkMainThread()
|
||||
val listener = View.OnLongClickListener {
|
||||
trySend(Unit)
|
||||
if (withHaptic) {
|
||||
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
}
|
||||
true
|
||||
}
|
||||
setOnLongClickListener(listener)
|
||||
awaitClose { setOnClickListener(null) }
|
||||
}.conflate()
|
||||
|
||||
fun EditText.textChanges(): Flow<CharSequence> = callbackFlow {
|
||||
checkMainThread()
|
||||
val listener = object : TextWatcher {
|
||||
|
|
|
@ -94,7 +94,6 @@ import com.anytypeio.anytype.core_ui.views.BodyCalloutRegular
|
|||
import com.anytypeio.anytype.core_ui.views.BodyRegular
|
||||
import com.anytypeio.anytype.core_ui.views.Caption1Medium
|
||||
import com.anytypeio.anytype.core_ui.views.Caption2Semibold
|
||||
import com.anytypeio.anytype.core_ui.views.ModalTitle
|
||||
import com.anytypeio.anytype.core_ui.views.Title1
|
||||
import com.anytypeio.anytype.core_ui.views.fontInterRegular
|
||||
import com.anytypeio.anytype.emojifier.Emojifier
|
||||
|
@ -917,7 +916,7 @@ fun ObjectTypesList(
|
|||
is TemplateObjectTypeView.Item -> {
|
||||
val borderWidth: Dp
|
||||
val borderColor: Color
|
||||
if (item.isDefault) {
|
||||
if (item.isSelected) {
|
||||
borderWidth = 2.dp
|
||||
borderColor = colorResource(id = R.color.palette_system_amber_50)
|
||||
} else {
|
||||
|
|
10
core-ui/src/main/res/drawable/ic_clear_18.xml
Normal file
10
core-ui/src/main/res/drawable/ic_clear_18.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="19dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="18">
|
||||
<path
|
||||
android:pathData="M17.115,9C17.115,13.418 13.533,17 9.115,17C4.696,17 1.115,13.418 1.115,9C1.115,4.582 4.696,1 9.115,1C13.533,1 17.115,4.582 17.115,9ZM5.69,5.576C5.925,5.341 6.305,5.341 6.539,5.576L9.115,8.151L11.691,5.576C11.925,5.341 12.305,5.341 12.539,5.576C12.773,5.81 12.773,6.19 12.539,6.424L9.963,9L12.539,11.576C12.773,11.81 12.773,12.19 12.539,12.424C12.305,12.659 11.925,12.659 11.691,12.424L9.115,9.849L6.539,12.424C6.305,12.659 5.925,12.659 5.69,12.424C5.456,12.19 5.456,11.81 5.69,11.576L8.266,9L5.69,6.424C5.456,6.19 5.456,5.81 5.69,5.576Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
|
@ -0,0 +1,16 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="44dp"
|
||||
android:height="44dp"
|
||||
android:viewportWidth="44"
|
||||
android:viewportHeight="44">
|
||||
<path
|
||||
android:pathData="M22,0L22,0A22,22 0,0 1,44 22L44,22A22,22 0,0 1,22 44L22,44A22,22 0,0 1,0 22L0,22A22,22 0,0 1,22 0z"
|
||||
android:strokeAlpha="0.2"
|
||||
android:fillColor="@color/palette_dark_red"
|
||||
android:fillAlpha="0.2"/>
|
||||
<path
|
||||
android:pathData="M24.76,34C24.517,34 24.306,33.823 24.247,33.569L19.37,12.889L17.189,22.14C17.129,22.394 16.917,22.571 16.675,22.571L10.53,22.571C10.237,22.571 10,22.315 10,22C10,21.684 10.237,21.428 10.53,21.428H16.263L18.857,10.431C18.917,10.177 19.128,10 19.37,10C19.612,10 19.824,10.177 19.883,10.431L24.76,31.111L26.941,21.86C27.001,21.606 27.212,21.429 27.454,21.429H33.47C33.763,21.429 34,21.685 34,22C34,22.316 33.763,22.572 33.47,22.572L27.866,22.572L25.273,33.569C25.213,33.823 25.002,34 24.76,34H24.76Z"
|
||||
android:strokeWidth="0.6"
|
||||
android:fillColor="@color/palette_system_red"
|
||||
android:strokeColor="@color/palette_system_red"/>
|
||||
</vector>
|
10
core-ui/src/main/res/drawable/ic_search_18.xml
Normal file
10
core-ui/src/main/res/drawable/ic_search_18.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="19dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="18">
|
||||
<path
|
||||
android:pathData="M16.676,14.574L12.843,10.74C13.531,9.802 13.899,8.67 13.893,7.508C13.88,4.474 11.427,2.018 8.394,2C6.942,1.993 5.549,2.568 4.523,3.595C3.497,4.622 2.925,6.017 2.933,7.468C2.947,10.502 5.4,12.958 8.433,12.976C9.6,12.981 10.737,12.609 11.675,11.915L11.679,11.912L15.508,15.743C15.715,15.96 16.024,16.048 16.315,15.973C16.605,15.897 16.832,15.67 16.907,15.38C16.982,15.089 16.894,14.781 16.676,14.574ZM8.429,11.878C6.003,11.864 4.04,9.899 4.029,7.472C4.023,6.311 4.481,5.196 5.301,4.374C6.122,3.552 7.236,3.093 8.397,3.098C10.824,3.112 12.787,5.077 12.797,7.504C12.804,8.665 12.346,9.78 11.526,10.602C10.705,11.423 9.591,11.883 8.429,11.878Z"
|
||||
android:fillColor="@color/glyph_active"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
9
core-ui/src/main/res/drawable/ic_the_everything_app.xml
Normal file
9
core-ui/src/main/res/drawable/ic_the_everything_app.xml
Normal file
File diff suppressed because one or more lines are too long
|
@ -147,8 +147,8 @@ inline fun <T, R> Iterable<T>.allUniqueBy(transform: (T) -> R): Boolean {
|
|||
}
|
||||
|
||||
fun Long.readableFileSize(): String {
|
||||
if (this <= 0) return "0"
|
||||
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||
if (this <= 0) return "Zero KB"
|
||||
val units = arrayOf("B", "KB", "MB", "GB", "TB")
|
||||
val digitGroups = (log10(this.toDouble()) / log10(1024.0)).toInt()
|
||||
return DecimalFormat("#,##0.#").format(this / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
|
||||
}
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.core_models.FileLimits
|
|||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.NodeUsageInfo
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectView
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -873,8 +874,8 @@ class BlockDataRepository(
|
|||
return remote.setQueryToSet(command)
|
||||
}
|
||||
|
||||
override suspend fun fileSpaceUsage(space: SpaceId): FileLimits {
|
||||
return remote.fileSpaceUsage(space)
|
||||
override suspend fun nodeUsage(): NodeUsageInfo {
|
||||
return remote.nodeUsage()
|
||||
}
|
||||
|
||||
override suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload {
|
||||
|
@ -888,4 +889,8 @@ class BlockDataRepository(
|
|||
override suspend fun createTemplateFromObject(ctx: Id): Id {
|
||||
return remote.createTemplateFromObject(ctx)
|
||||
}
|
||||
|
||||
override suspend fun debugStackGoroutines(path: String) {
|
||||
return remote.debugStackGoroutines(path)
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import com.anytypeio.anytype.core_models.DVViewerType
|
|||
import com.anytypeio.anytype.core_models.FileLimits
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.NodeUsageInfo
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectView
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -373,10 +374,11 @@ interface BlockRemote {
|
|||
suspend fun sortDataViewViewRelation(command: Command.SortRelations): Payload
|
||||
suspend fun addObjectToCollection(command: Command.AddObjectToCollection): Payload
|
||||
suspend fun setQueryToSet(command: Command.SetQueryToSet): Payload
|
||||
suspend fun fileSpaceUsage(space: SpaceId): FileLimits
|
||||
suspend fun nodeUsage(): NodeUsageInfo
|
||||
|
||||
suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload
|
||||
|
||||
suspend fun duplicateObjectsList(ids: List<Id>): List<Id>
|
||||
suspend fun createTemplateFromObject(ctx: Id): Id
|
||||
suspend fun debugStackGoroutines(path: String)
|
||||
}
|
|
@ -7,8 +7,9 @@ import com.anytypeio.anytype.core_models.ObjectWrapper
|
|||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetObjectTypes(
|
||||
class GetObjectTypes @Inject constructor(
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<GetObjectTypes.Params, List<ObjectWrapper.Type>>(dispatchers.io) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.anytypeio.anytype.core_models.FileLimits
|
|||
import com.anytypeio.anytype.core_models.Hash
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.Key
|
||||
import com.anytypeio.anytype.core_models.NodeUsageInfo
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectView
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
|
@ -186,11 +187,11 @@ interface BlockRepository {
|
|||
): Payload
|
||||
|
||||
suspend fun searchObjects(
|
||||
sorts: List<DVSort>,
|
||||
filters: List<DVFilter>,
|
||||
fulltext: String,
|
||||
offset: Int,
|
||||
limit: Int,
|
||||
sorts: List<DVSort> = emptyList(),
|
||||
filters: List<DVFilter> = emptyList(),
|
||||
fulltext: String = "",
|
||||
offset: Int = 0,
|
||||
limit: Int = 0,
|
||||
keys: List<Id> = emptyList()
|
||||
): List<Struct>
|
||||
|
||||
|
@ -423,8 +424,9 @@ interface BlockRepository {
|
|||
suspend fun sortDataViewViewRelation(command: Command.SortRelations): Payload
|
||||
suspend fun addObjectToCollection(command: Command.AddObjectToCollection): Payload
|
||||
suspend fun setQueryToSet(command: Command.SetQueryToSet): Payload
|
||||
suspend fun fileSpaceUsage(space: SpaceId): FileLimits
|
||||
suspend fun nodeUsage(): NodeUsageInfo
|
||||
suspend fun setInternalFlags(command: Command.SetInternalFlags): Payload
|
||||
suspend fun duplicateObjectsList(ids: List<Id>): List<Id>
|
||||
suspend fun createTemplateFromObject(ctx: Id): Id
|
||||
suspend fun debugStackGoroutines(path: String)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.anytypeio.anytype.domain.debugging
|
||||
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class DebugGoroutines @Inject constructor(
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<DebugGoroutines.Params, Unit>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Params) {
|
||||
repo.debugStackGoroutines(params.path)
|
||||
}
|
||||
|
||||
data class Params(val path: String)
|
||||
}
|
|
@ -28,14 +28,7 @@ interface StorelessSubscriptionContainer {
|
|||
|
||||
fun subscribe(searchParams: StoreSearchParams): Flow<List<ObjectWrapper.Basic>>
|
||||
fun subscribe(searchParams: StoreSearchByIdsParams) : Flow<List<ObjectWrapper.Basic>>
|
||||
|
||||
suspend fun unsubscribe(subscriptions: List<Id>)
|
||||
|
||||
companion object {
|
||||
const val SUBSCRIPTION_SETTINGS = "settings-subscription"
|
||||
const val SUBSCRIPTION_PROFILE = "profile-subscription"
|
||||
const val SUBSCRIPTION_TEMPLATES = "templates-subscription"
|
||||
}
|
||||
|
||||
class Impl @Inject constructor(
|
||||
private val repo: BlockRepository,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.library.processors
|
||||
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.SubscriptionEvent
|
||||
import com.anytypeio.anytype.domain.library.SubscriptionObject
|
||||
|
||||
|
@ -15,7 +16,7 @@ class EventSetProcessor : SubscriptionEventProcessor<SubscriptionEvent.Set> {
|
|||
indexOfItem,
|
||||
SubscriptionObject(
|
||||
event.target,
|
||||
com.anytypeio.anytype.core_models.ObjectWrapper.Basic(event.data)
|
||||
ObjectWrapper.Basic(event.data)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
|
@ -23,7 +24,7 @@ class EventSetProcessor : SubscriptionEventProcessor<SubscriptionEvent.Set> {
|
|||
0,
|
||||
SubscriptionObject(
|
||||
event.target,
|
||||
com.anytypeio.anytype.core_models.ObjectWrapper.Basic(event.data)
|
||||
ObjectWrapper.Basic(event.data)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.emitAll
|
|||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.scan
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class ObjectTypesSubscriptionContainer(
|
||||
private val repo: BlockRepository,
|
||||
|
@ -127,6 +128,14 @@ class ObjectTypesSubscriptionContainer(
|
|||
*/
|
||||
private fun subscribe(subscriptions: List<Id>) = channel.subscribe(subscriptions)
|
||||
|
||||
suspend fun unsubscribe() = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
repo.cancelObjectSearchSubscription(
|
||||
listOf(SUBSCRIPTION_ID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val subscription: Id,
|
||||
val sorts: List<DVSort>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.anytypeio.anytype.domain.search
|
||||
|
||||
import com.anytypeio.anytype.core_models.Config
|
||||
import com.anytypeio.anytype.core_models.DVFilter
|
||||
import com.anytypeio.anytype.core_models.DVFilterCondition
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
|
@ -9,67 +10,76 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ObjectTypesSubscriptionManager (
|
||||
private val scope: CoroutineScope = GlobalScope,
|
||||
private val subscription: ObjectTypesSubscriptionContainer,
|
||||
private val container: ObjectTypesSubscriptionContainer,
|
||||
private val spaceManager: SpaceManager
|
||||
) {
|
||||
|
||||
private val pipeline = spaceManager.observe().flatMapLatest { config ->
|
||||
val params = buildParams(config)
|
||||
container.observe(params)
|
||||
}
|
||||
|
||||
private var job: Job? = null
|
||||
|
||||
fun onStart() {
|
||||
job?.cancel()
|
||||
job = scope.launch {
|
||||
val params = ObjectTypesSubscriptionContainer.Params(
|
||||
subscription = ObjectTypesSubscriptionContainer.SUBSCRIPTION_ID,
|
||||
filters = listOf(
|
||||
DVFilter(
|
||||
relation = Relations.LAYOUT,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = ObjectType.Layout.OBJECT_TYPE.code.toDouble()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.SPACE_ID,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = spaceManager.get()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.IS_DELETED,
|
||||
condition = DVFilterCondition.NOT_EQUAL,
|
||||
value = true
|
||||
),
|
||||
),
|
||||
limit = 0,
|
||||
offset = 0L,
|
||||
sorts = emptyList(),
|
||||
sources = emptyList(),
|
||||
keys = listOf(
|
||||
Relations.ID,
|
||||
Relations.NAME,
|
||||
Relations.IS_HIDDEN,
|
||||
Relations.IS_DELETED,
|
||||
Relations.IS_ARCHIVED,
|
||||
Relations.SMARTBLOCKTYPES,
|
||||
Relations.LAYOUT,
|
||||
Relations.DESCRIPTION,
|
||||
Relations.ICON_EMOJI,
|
||||
Relations.SOURCE_OBJECT,
|
||||
Relations.IS_READ_ONLY,
|
||||
Relations.RECOMMENDED_LAYOUT,
|
||||
Relations.DEFAULT_TEMPLATE_ID,
|
||||
Relations.SPACE_ID,
|
||||
Relations.UNIQUE_KEY
|
||||
),
|
||||
ignoreWorkspace = true
|
||||
)
|
||||
subscription.observe(params).collect()
|
||||
}
|
||||
job = scope.launch { pipeline.collect() }
|
||||
}
|
||||
|
||||
private fun buildParams(config: Config) =
|
||||
ObjectTypesSubscriptionContainer.Params(
|
||||
subscription = ObjectTypesSubscriptionContainer.SUBSCRIPTION_ID,
|
||||
filters = listOf(
|
||||
DVFilter(
|
||||
relation = Relations.LAYOUT,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = ObjectType.Layout.OBJECT_TYPE.code.toDouble()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.SPACE_ID,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = config.space
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.IS_DELETED,
|
||||
condition = DVFilterCondition.NOT_EQUAL,
|
||||
value = true
|
||||
),
|
||||
),
|
||||
limit = 0,
|
||||
offset = 0L,
|
||||
sorts = emptyList(),
|
||||
sources = emptyList(),
|
||||
keys = listOf(
|
||||
Relations.ID,
|
||||
Relations.NAME,
|
||||
Relations.IS_HIDDEN,
|
||||
Relations.IS_DELETED,
|
||||
Relations.IS_ARCHIVED,
|
||||
Relations.SMARTBLOCKTYPES,
|
||||
Relations.LAYOUT,
|
||||
Relations.DESCRIPTION,
|
||||
Relations.ICON_EMOJI,
|
||||
Relations.SOURCE_OBJECT,
|
||||
Relations.IS_READ_ONLY,
|
||||
Relations.RECOMMENDED_LAYOUT,
|
||||
Relations.DEFAULT_TEMPLATE_ID,
|
||||
Relations.SPACE_ID,
|
||||
Relations.UNIQUE_KEY
|
||||
),
|
||||
ignoreWorkspace = true
|
||||
)
|
||||
|
||||
fun onStop() {
|
||||
job?.cancel()
|
||||
job = null
|
||||
scope.launch {
|
||||
container.unsubscribe()
|
||||
job?.cancel()
|
||||
job = null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import kotlinx.coroutines.flow.emitAll
|
|||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.scan
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class RelationsSubscriptionContainer(
|
||||
private val repo: BlockRepository,
|
||||
|
@ -122,11 +123,21 @@ class RelationsSubscriptionContainer(
|
|||
}.flowOn(dispatchers.io)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns events for subscriptions and dependent subscriptions
|
||||
*/
|
||||
private fun subscribe(subscriptions: List<Id>) = channel.subscribe(subscriptions)
|
||||
|
||||
suspend fun unsubscribe() = withContext(dispatchers.io) {
|
||||
runCatching {
|
||||
repo.cancelObjectSearchSubscription(
|
||||
listOf(SUBSCRIPTION_ID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(
|
||||
val subscription: Id,
|
||||
val sorts: List<DVSort>,
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.search
|
|||
|
||||
import com.anytypeio.anytype.core_models.DVFilter
|
||||
import com.anytypeio.anytype.core_models.DVFilterCondition
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
|
@ -10,71 +11,78 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
class RelationsSubscriptionManager @Inject constructor(
|
||||
private val scope: CoroutineScope = GlobalScope,
|
||||
private val subscription: RelationsSubscriptionContainer,
|
||||
private val container: RelationsSubscriptionContainer,
|
||||
private val spaceManager: SpaceManager
|
||||
) {
|
||||
private val pipeline = spaceManager.observe().flatMapLatest { config ->
|
||||
val params = buildParams(config.space)
|
||||
container.observe(params)
|
||||
}
|
||||
|
||||
private var job: Job? = null
|
||||
|
||||
fun onStart() {
|
||||
job?.cancel()
|
||||
job = scope.launch {
|
||||
val params = RelationsSubscriptionContainer.Params(
|
||||
subscription = RelationsSubscriptionContainer.SUBSCRIPTION_ID,
|
||||
filters = listOf(
|
||||
DVFilter(
|
||||
relation = Relations.LAYOUT,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = ObjectType.Layout.RELATION.code.toDouble()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.IS_DELETED,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = false
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.SPACE_ID,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = spaceManager.get()
|
||||
)
|
||||
),
|
||||
limit = 0,
|
||||
offset = 0L,
|
||||
sorts = emptyList(),
|
||||
sources = emptyList(),
|
||||
keys = listOf(
|
||||
Relations.ID,
|
||||
Relations.SPACE_ID,
|
||||
Relations.TYPE,
|
||||
Relations.LAYOUT,
|
||||
Relations.NAME,
|
||||
Relations.RELATION_FORMAT,
|
||||
Relations.RELATION_KEY,
|
||||
Relations.SCOPE,
|
||||
Relations.IS_READ_ONLY,
|
||||
Relations.IS_HIDDEN,
|
||||
Relations.IS_DELETED,
|
||||
Relations.IS_ARCHIVED,
|
||||
Relations.IS_FAVORITE,
|
||||
Relations.RESTRICTIONS,
|
||||
Relations.MAX_COUNT,
|
||||
Relations.RELATION_READ_ONLY_VALUE,
|
||||
Relations.RELATION_DEFAULT_VALUE,
|
||||
Relations.RELATION_FORMAT_OBJECT_TYPES
|
||||
),
|
||||
ignoreWorkspace = true
|
||||
)
|
||||
subscription.observe(params).collect()
|
||||
}
|
||||
job = scope.launch { pipeline.collect() }
|
||||
}
|
||||
|
||||
private fun buildParams(space: Id) = RelationsSubscriptionContainer.Params(
|
||||
subscription = RelationsSubscriptionContainer.SUBSCRIPTION_ID,
|
||||
filters = listOf(
|
||||
DVFilter(
|
||||
relation = Relations.LAYOUT,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = ObjectType.Layout.RELATION.code.toDouble()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.IS_DELETED,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = false
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.SPACE_ID,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = space
|
||||
)
|
||||
),
|
||||
limit = 0,
|
||||
offset = 0L,
|
||||
sorts = emptyList(),
|
||||
sources = emptyList(),
|
||||
keys = listOf(
|
||||
Relations.ID,
|
||||
Relations.SPACE_ID,
|
||||
Relations.TYPE,
|
||||
Relations.LAYOUT,
|
||||
Relations.NAME,
|
||||
Relations.RELATION_FORMAT,
|
||||
Relations.RELATION_KEY,
|
||||
Relations.SCOPE,
|
||||
Relations.IS_READ_ONLY,
|
||||
Relations.IS_HIDDEN,
|
||||
Relations.IS_DELETED,
|
||||
Relations.IS_ARCHIVED,
|
||||
Relations.IS_FAVORITE,
|
||||
Relations.RESTRICTIONS,
|
||||
Relations.MAX_COUNT,
|
||||
Relations.RELATION_READ_ONLY_VALUE,
|
||||
Relations.RELATION_DEFAULT_VALUE,
|
||||
Relations.RELATION_FORMAT_OBJECT_TYPES
|
||||
),
|
||||
ignoreWorkspace = true
|
||||
)
|
||||
|
||||
fun onStop() {
|
||||
job?.cancel()
|
||||
job = null
|
||||
scope.launch {
|
||||
container.unsubscribe()
|
||||
job?.cancel()
|
||||
job = null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.anytypeio.anytype.domain.spaces
|
||||
|
||||
import com.anytypeio.anytype.core_models.DVFilter
|
||||
import com.anytypeio.anytype.core_models.DVFilterCondition
|
||||
import com.anytypeio.anytype.core_models.Id
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
import javax.inject.Inject
|
||||
|
||||
class GetSpaceView @Inject constructor(
|
||||
private val repo: BlockRepository,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
): ResultInteractor<Id, ObjectWrapper.Basic?>(dispatchers.io) {
|
||||
override suspend fun doWork(params: Id): ObjectWrapper.Basic? {
|
||||
val result = repo.searchObjects(
|
||||
filters = buildList {
|
||||
add(
|
||||
DVFilter(
|
||||
relation = Relations.ID,
|
||||
value = params,
|
||||
condition = DVFilterCondition.EQUAL
|
||||
)
|
||||
)
|
||||
},
|
||||
limit = 1
|
||||
).firstOrNull()
|
||||
return if (result != null) {
|
||||
ObjectWrapper.Basic(result)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package com.anytypeio.anytype.domain.spaces
|
||||
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.restrictions.SpaceStatus
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.config.ConfigStorage
|
||||
import com.anytypeio.anytype.domain.debugging.Logger
|
||||
import com.anytypeio.anytype.domain.library.StoreSearchByIdsParams
|
||||
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
|
||||
import com.anytypeio.anytype.domain.workspace.SpaceManager
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SpaceDeletedStatusWatcher @Inject constructor(
|
||||
private val scope: CoroutineScope,
|
||||
private val container: StorelessSubscriptionContainer,
|
||||
private val spaceManager: SpaceManager,
|
||||
private val dispatchers: AppCoroutineDispatchers,
|
||||
private val configStorage: ConfigStorage,
|
||||
private val logger: Logger
|
||||
) {
|
||||
|
||||
private val jobs = mutableListOf<Job>()
|
||||
|
||||
fun onStart() {
|
||||
jobs += scope.launch(dispatchers.io) {
|
||||
spaceManager
|
||||
.observe()
|
||||
.flatMapLatest { config ->
|
||||
container.subscribe(
|
||||
searchParams = StoreSearchByIdsParams(
|
||||
subscription = GLOBAL_SPACE_VIEW_SUBSCRIPTION,
|
||||
targets = listOf(config.spaceView),
|
||||
keys = buildList {
|
||||
add(Relations.ID)
|
||||
add(Relations.TARGET_SPACE_ID)
|
||||
add(Relations.SPACE_ACCOUNT_STATUS)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
.mapNotNull { results -> results.firstOrNull() }
|
||||
.onEach { result ->
|
||||
val spaceView = result.let {
|
||||
ObjectWrapper.SpaceView(it.map)
|
||||
}
|
||||
if (spaceView.spaceAccountStatus == SpaceStatus.SPACE_DELETED) {
|
||||
logger.logWarning("Current space is deleted")
|
||||
val accountConfig = configStorage.getOrNull()
|
||||
if (accountConfig != null) {
|
||||
logger.logWarning("Account config found. Switching to default space.")
|
||||
spaceManager.set(accountConfig.space)
|
||||
} else {
|
||||
logger.logWarning("Account config not found. Resetting space.")
|
||||
spaceManager.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
fun onStop() {
|
||||
scope.launch(dispatchers.io) {
|
||||
container.unsubscribe(listOf(GLOBAL_SPACE_VIEW_SUBSCRIPTION))
|
||||
with(jobs) {
|
||||
forEach { it.cancel() }
|
||||
clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val GLOBAL_SPACE_VIEW_SUBSCRIPTION = "subscription.global.space-view"
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import com.anytypeio.anytype.core_models.DVFilter
|
|||
import com.anytypeio.anytype.core_models.DVFilterCondition
|
||||
import com.anytypeio.anytype.core_models.DVSort
|
||||
import com.anytypeio.anytype.core_models.ObjectType
|
||||
import com.anytypeio.anytype.core_models.ObjectTypeIds
|
||||
import com.anytypeio.anytype.core_models.ObjectWrapper
|
||||
import com.anytypeio.anytype.core_models.Relations
|
||||
import com.anytypeio.anytype.core_models.primitives.TypeId
|
||||
|
@ -52,6 +53,15 @@ class GetTemplates(
|
|||
relation = Relations.SPACE_ID,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = spaceManager.get()
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.TYPE_UNIQUE_KEY,
|
||||
condition = DVFilterCondition.EQUAL,
|
||||
value = ObjectTypeIds.TEMPLATE
|
||||
),
|
||||
DVFilter(
|
||||
relation = Relations.ID,
|
||||
condition = DVFilterCondition.NOT_EMPTY
|
||||
)
|
||||
),
|
||||
keys = listOf(
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package com.anytypeio.anytype.domain.workspace
|
||||
|
||||
import com.anytypeio.anytype.core_models.FileLimits
|
||||
import com.anytypeio.anytype.core_models.primitives.SpaceId
|
||||
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
|
||||
import com.anytypeio.anytype.domain.base.ResultInteractor
|
||||
import com.anytypeio.anytype.domain.block.repo.BlockRepository
|
||||
|
||||
class FileSpaceUsage(
|
||||
private val repo: BlockRepository,
|
||||
private val spaceManager: SpaceManager,
|
||||
dispatchers: AppCoroutineDispatchers
|
||||
) : ResultInteractor<Unit, FileLimits>(dispatchers.io) {
|
||||
|
||||
override suspend fun doWork(params: Unit): FileLimits {
|
||||
return repo.fileSpaceUsage(space = SpaceId(spaceManager.get()))
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user