Compare commits

...

89 Commits

Author SHA1 Message Date
konstantiniiv
4b3bdf197c DROID-2107 Merge branch 'release/0-27-0' into droid-2107-picker-crash
# Conflicts:
#	app/src/main/java/com/anytypeio/anytype/ui/editor/PickerDelegate.kt
2023-12-25 13:41:11 +01:00
Evgenii Kozlov
de027e3563
DROID-2092 App | Fix | Fix crashes from the latest release (#746) 2023-12-25 13:39:16 +01:00
konstantiniiv
615f8a8615 DROID-2107 code style 2023-12-25 13:23:03 +01:00
konstantiniiv
cd4209ff9a DROID-2107 fix start file picker 2023-12-25 13:18:45 +01:00
konstantiniiv
a79e607835 DROID-2107 fix 2023-12-25 13:11:14 +01:00
Evgenii Kozlov
7f996c455a
Droid 2092 Editor | Fix | Do not crash when entering select mode in object with unsupported blocks + Fix crash related to observing profile icon (#745) 2023-12-25 12:37:49 +01:00
Any Association [bot]
175ca75128
l10n | Enhancement (#744)
(cherry picked from commit bcc99764df)
2023-12-24 12:28:12 +01:00
Any Association [bot]
64882b7d9c
l10n | Enhancement (#743)
(cherry picked from commit 5d0c789a5b)
2023-12-24 12:28:09 +01:00
Any Association [bot]
788341aa78
l10n | Enhancement (#742)
(cherry picked from commit df1585b062)
2023-12-24 12:28:07 +01:00
Any Association [bot]
2da8d90603
l10n | Enhancement (#741) 2023-12-24 12:28:00 +01:00
Any Association [bot]
8b2c4124cc
l10n | Enhancement (#740)
(cherry picked from commit f86c545f1f)
2023-12-24 12:25:17 +01:00
Any Association [bot]
d41bdd0a37
l10n | Enhancement (#739)
(cherry picked from commit 581861a6a0)
2023-12-24 12:25:17 +01:00
uburoiubu
25bc621903
v0.27.15 2023-12-22 14:49:21 +01:00
Konstantin Ivanov
ac507dcc2d
DROID-2079 Collection | Prefilled objects (#738) 2023-12-22 14:29:31 +01:00
Evgenii Kozlov
24c27a0dbc
DROID-2049 Analytics | Basic analytics for sharing extension (#737) 2023-12-22 14:26:30 +01:00
uburoiubu
3ce80bfefc
v0.27.14 2023-12-22 12:36:20 +01:00
uburoiubu
9b0c51fd5a
DROID-2098 Protocol | Enhancement | MW 0.30.3 2023-12-22 12:35:32 +01:00
uburoiubu
bf62043064
v.0.27.13 2023-12-22 12:21:31 +01:00
Evgenii Kozlov
e8ccfad117
DROID-2054 Sharing extension | Fix | Synchronize sharing extension with account start (#736) 2023-12-22 12:19:41 +01:00
uburoiubu
d838cdeac4
DROID-2054 Sharing extension | Fix | Do not crash when sharing extension is launched before account is started 2023-12-22 11:37:55 +01:00
uburoiubu
00c742b3d9
v.0.27.12 2023-12-22 10:37:32 +01:00
uburoiubu
6ed11ecf45
DROID-2097 Protocol | Enhancement | MW 0.30.2 2023-12-22 10:36:33 +01:00
Evgenii Kozlov
cd7336cc9f
DROID-2078 Onboarding | Fix | Recovery-phrase input design fixes for login-flow (#735) 2023-12-21 19:30:30 +01:00
uburoiubu
d295876ca8
v0.27.11 2023-12-21 14:48:36 +01:00
Konstantin Ivanov
30d39bdf94
DROID-2091 Protocol | Enhancement | MW 0.30.1 (#734) 2023-12-21 14:31:34 +01:00
uburoiubu
12960b027d
v0.27.9 2023-12-21 10:52:19 +01:00
Konstantin Ivanov
8db6837471
DROID-2086 Protocol | Enhancement | MW 0.30.0 (#733) 2023-12-20 22:40:40 +01:00
uburoiubu
ca0e79f3ea
DROID-2050 Objects | Fix | Revert expand/collapse behavior for new type picker 2023-12-20 17:55:29 +01:00
uburoiubu
4a251354ab
v0.27.8 2023-12-20 17:35:32 +01:00
Konstantin Ivanov
d1558add81
DROID-2050 Create Object | Fix | Restricted changing type to a collection or set in an object (#730) 2023-12-20 17:32:38 +01:00
Evgenii Kozlov
11195df494
DROID-2081 Sets | Fix | Do not show objects with system layout in sets (#732) 2023-12-20 17:24:59 +01:00
Evgenii Kozlov
01c729216f
DROID-2050 Objects | Tech | Provide excluded types keys for create-object-of-type MVVM components (#729) 2023-12-20 15:19:01 +01:00
Evgenii Kozlov
08531d8393
DROID-2077 Relations | Fix | Allow reloading bookmark source (#728) 2023-12-20 15:04:55 +01:00
Evgenii Kozlov
79ff246858
DROID-2054 Sharing extension | Fix | Fix type option menu (#727) 2023-12-20 14:38:55 +01:00
Konstantin Ivanov
e25023edc3
DROID-2058 Relations | Object type is not displayed first of featured relations (#726) 2023-12-20 14:24:43 +01:00
Konstantin Ivanov
d6906b73be
DROID-1922 Type screen | Fix | User interaction and screen state (#725) 2023-12-20 13:40:26 +01:00
uburoiubu
fbc7a25b1c
v0.27.7 2023-12-19 23:07:29 +01:00
Evgenii Kozlov
c58ec46924
DROID-2075 App | Fix | Fix crash in emojifier (#720) 2023-12-19 23:06:15 +01:00
Konstantin Ivanov
e527260faf
DROID-2066 Templates | Fix | Default template doesn't apply (#723) 2023-12-19 23:04:38 +01:00
Konstantin Ivanov
5c056aebf5
DROID-2055 Templates | Fix | Different background color and menu in dark (#722) 2023-12-19 22:42:57 +01:00
Evgenii Kozlov
c36a90b2e6
DROID-2076 Settings | Fix | Main-settings screen might not be scrollable on very small devices (#721) 2023-12-19 22:26:16 +01:00
uburoiubu
3f13e93d15
v0.27.6 2023-12-19 15:56:31 +01:00
Evgenii Kozlov
9db9234c2c
DROID-2054 Sharing extensions | Fix | Fix selected-space logic (#718) 2023-12-19 15:55:51 +01:00
Konstantin Ivanov
8feab35098
DROID-1602 Self hosting | Fix | Network mode config (#719) 2023-12-19 15:54:46 +01:00
uburoiubu
c0d9bcc89b
DROID-2071 Protocol | Enhancement | MW 0.30.0-rc8 2023-12-19 15:30:35 +01:00
Evgenii Kozlov
f53be3f926
DROID-2067 Onboarding | Fix | Back navigation is broken when rapidly pressing back button twice on set-profile-name screen (#716) 2023-12-19 15:23:49 +01:00
Konstantin Ivanov
ec52dff7fb
DROID-2020 Self-host | Fix | Sync status local (#717) 2023-12-19 15:17:57 +01:00
Any Association [bot]
10cccab7fd
l10n | Enhancement (#712)
(cherry picked from commit efb6d13db6)
2023-12-19 13:25:13 +01:00
Evgenii Kozlov
231c6eda2f
DROID-2054 Sharing Extensions | Fix | Do not allow creating bookmark object when shared data is not a URL (#714) 2023-12-19 12:55:44 +01:00
Evgenii Kozlov
b663cd5960
DROID-1882 Sharing Extension | Enhancement | Add origin source when adding content from sharing extension (#713) 2023-12-19 12:55:13 +01:00
uburoiubu
915e54c037
v0.27.5 2023-12-18 23:29:09 +01:00
Any Association [bot]
968c4e1f35
l10n | Enhancement (#711)
(cherry picked from commit 2203a8a924)
2023-12-18 23:28:13 +01:00
Any Association [bot]
25d985c448
l10n | Enhancement (#707)
(cherry picked from commit be1a0ef45f)
2023-12-18 23:28:11 +01:00
Konstantin Ivanov
ce96af8cd9
DROID-1923 Backlinks | Fix | Design and navigation fixes (#710) 2023-12-18 21:59:06 +01:00
Konstantin Ivanov
665eb8d9e8
DROID-2064 Protocol | Enhancement | MW 0.30.0-rc7 (#709) 2023-12-18 13:47:35 +01:00
Konstantin Ivanov
1114cc3517
DROID-1838 Relations | Fix | Add file screen design fixes (#708) 2023-12-18 13:47:18 +01:00
Any Association [bot]
9c65811634
l10n | Enhancement (#706)
Co-authored-by: Evgenii Kozlov <ubuphobos@gmail.com>
(cherry picked from commit 70b9414dbf)
2023-12-18 11:04:21 +01:00
konstantiniiv
a5df9cc362 v0.27.4 2023-12-18 10:33:16 +01:00
uburoiubu
438162cdfb
DROID-2062 Protocol | Enhancement | MW 0.30.0-rc6 2023-12-15 18:38:37 +01:00
Any Association [bot]
9c52ef4c6b
l10n | Enhancement (#705)
(cherry picked from commit c6f8ea04bc)
2023-12-15 18:35:47 +01:00
Any Association [bot]
d64d4f00c4
l10n | Enhancement (#702)
(cherry picked from commit 53d25f7c2c)
2023-12-15 14:18:35 +01:00
Any Association [bot]
aed9f1a720
l10n | Enhancement (#700)
(cherry picked from commit 31f3605a4d)
2023-12-15 14:18:32 +01:00
uburoiubu
8b41c9cd34
v0.27.3 2023-12-15 13:23:26 +01:00
Evgenii Kozlov
d7434e7336
DROID-1803 App | Tech | Kotlin + Library updates (#704) 2023-12-15 13:22:30 +01:00
Konstantin Ivanov
ecb75efbe7
DROID-2052 Create objets | Fix | Navigation to sets (#703) 2023-12-15 11:09:23 +01:00
Evgenii Kozlov
ba76dc3535
DROID-2029 Relations | Fix | Mapping number value to pretty text for relation 'Origin' (#701) 2023-12-14 16:18:50 +01:00
Evgenii Kozlov
bf3a0d73ff
DROID-2048 Relations | Tech | Refact relation object value parsing (#699) 2023-12-14 15:38:46 +01:00
Konstantin Ivanov
26a23de502
DROID-2043 Objects | Backlinks | Hide, when value is empty (#698) 2023-12-14 15:10:23 +01:00
Any Association [bot]
dcb75d5e7f
l10n | Enhancement (#697)
(cherry picked from commit e4e92e48bf)
2023-12-14 14:04:40 +01:00
Evgenii Kozlov
7f78502cb0
DROID-2048 Relations | Fix | Profile-identity related fixes (#696) 2023-12-14 13:42:13 +01:00
Any Association [bot]
482534edca
l10n | Enhancement (#695)
Co-authored-by: Evgenii Kozlov <ubuphobos@gmail.com>
(cherry picked from commit fa4884912d)
2023-12-14 12:38:38 +01:00
Evgenii Kozlov
0f8eb37456
DROID-1652 App | Feature | Sharing extension MVP (#691)
(cherry picked from commit 53421ce574)
2023-12-14 12:38:30 +01:00
uburoiubu
4853266507
v0.27.2 2023-12-14 09:59:37 +01:00
Any Association [bot]
98b48aab7d
l10n | Enhancement (#694)
Co-authored-by: Evgenii Kozlov <ubuphobos@gmail.com>
(cherry picked from commit 988b8aa68a)
2023-12-14 09:59:05 +01:00
Konstantin Ivanov
b7543cbec9
DROID-2046 Design | New change type menu does not have top space (#693) 2023-12-13 22:08:45 +01:00
Konstantin Ivanov
55885effb5
DROID-1838 Relations | Fix | Adding files to relations, pt. 2 (#692) 2023-12-13 16:52:44 +01:00
Konstantin Ivanov
2a4e5b267c
DROID-2043 Backlinks | Fixes (#690) 2023-12-13 13:08:58 +01:00
uburoiubu
18a53cc916
DROID-2045 Protocol | Enhancement | MW 0.30.0-rc5 2023-12-13 12:53:57 +01:00
Konstantin Ivanov
bc2099f57c
DROID-1602 Analytics | Self hosting (#689) 2023-12-12 22:29:37 +01:00
Evgenii Kozlov
ecacddeade
DROID-2015 Editor | Fix | Show latex block as unsupported if its processor is unsupported (#688) 2023-12-12 21:44:04 +01:00
Any Association [bot]
21045d92a6
l10n | Enhancement (#686)
(cherry picked from commit fd0f44b8ec)
2023-12-12 18:10:41 +01:00
Konstantin Ivanov
3243280555
DROID-2039 Analytics | Any objects creation analytics (#687) 2023-12-12 17:03:53 +01:00
uburoiubu
8f4cdb1ec5
v0.27.1 2023-12-12 13:58:46 +01:00
Evgenii Kozlov
584afe0e97
DROID-1902 Multispaces | Fix | Improve soft input handling (#685) 2023-12-12 13:52:15 +01:00
Evgenii Kozlov
55ebc87413
DROID-2042 Protocol | Enhancement | MW 0.30.0-rc4 (#684) 2023-12-12 12:59:26 +01:00
Evgenii Kozlov
968b1fd385
DROID-1924 Types | Enhancement | Sort types by lastUsedDate (#683) 2023-12-12 12:55:16 +01:00
Evgenii Kozlov
5e5e4b0768
DROID-1881 App | Tech | Lib updates (#682) 2023-12-12 12:54:26 +01:00
Any Association [bot]
4fc3ff43fd
l10n | Enhancement (#681)
(cherry picked from commit c31a043720)
2023-12-12 12:05:16 +01:00
Any Association [bot]
0b1cd7b17f
l10n | Enhancement (#679)
(cherry picked from commit 8df314b0ac)
2023-12-12 11:50:06 +01:00
173 changed files with 3792 additions and 2280 deletions

3
.gitignore vendored
View File

@ -19,5 +19,4 @@
.externalNativeBuild
ktlint
.idea/*.xml
signing.properties
network.properties
signing.properties

View File

@ -13,6 +13,16 @@ android {
buildConfigField "boolean", "SEND_EVENTS", getProperty('config.enableAnalyticsForDebugBuilds')
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.analytics'
}

View File

@ -184,6 +184,17 @@ object EventsDictionary {
const val MENU_HELP_PRIVACY = "MenuHelpPrivacy"
const val MENU_HELP_CONTACT_US = "MenuHelpContact"
// Sharing extension
const val CLICK_ONBOARDING_TOOLTIP = "ClickOnboardingTooltip"
const val CLICK_ONBOARDING_TOOLTIP_ID_SHARING_EXTENSION = "SharingExtension"
const val CLICK_ONBOARDING_TOOLTIP_TYPE_SHARING_MENU = "ShareMenu"
const val CLICK_ONBOARDING_TOOLTIP_TYPE_CLOSE = "Close"
// Network mode
const val selectNetwork = "SelectNetwork"
const val uploadNetworkConfiguration = "UploadNetworkConfiguration"
enum class ScreenOnboardingStep(val value: String) {
VOID("Void"),
PHRASE("Phrase"),
@ -218,6 +229,8 @@ object EventsDictionary {
const val settings = "Settings"
const val screenDeletion = "ScreenDeletion"
const val navigation = "Navigation"
const val longTap = "LongTap"
const val sharingExtension = "SharingExtension"
}
object Type {
@ -228,6 +241,9 @@ object EventsDictionary {
const val dataView = "dataview"
const val block = "block"
const val bookmark = "bookmark"
const val anytype = "Anytype"
const val localOnly = "LocalOnly"
const val selfHost = "SelfHost"
}
object BlockAction {
@ -254,6 +270,7 @@ object EventsDictionary {
}
object EventsPropertiesKey {
const val id = "id"
const val tab = "tab"
const val route = "route"
const val type = "type"

View File

@ -118,15 +118,6 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
composeOptions {
kotlinCompilerExtensionVersion libs.versions.composeKotlinCompilerVersion.get()
}
@ -136,6 +127,15 @@ android {
compose true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
splits {
// Configures multiple APKs based on ABI.
abi {
@ -151,16 +151,6 @@ android {
namespace 'com.anytypeio.anytype'
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}
dependencies {
implementation project(':domain')

View File

@ -1,4 +1,4 @@
version.versionMajor=0
version.versionMinor=27
version.versionPatch=0
version.versionPatch=15
version.useDatedVersionName=false

View File

@ -21,6 +21,7 @@ import com.anytypeio.anytype.domain.`object`.ReloadObject
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectValueProvider
@ -57,6 +58,9 @@ class DisplayObjectRelationTextValueTest {
@Mock
lateinit var analytics: Analytics
@Mock
lateinit var storeOfObjectTypes: StoreOfObjectTypes
val root = MockDataFactory.randomUuid()
private val state: MutableStateFlow<ObjectState> = MutableStateFlow(ObjectState.Init)
@ -74,7 +78,8 @@ class DisplayObjectRelationTextValueTest {
),
values = DataViewObjectValueProvider(db = db, objectState = state),
reloadObject = reloadObject,
analytics = analytics
analytics = analytics,
storeOfObjectTypes = storeOfObjectTypes
)
}

View File

@ -19,6 +19,7 @@ import com.anytypeio.anytype.domain.`object`.ReloadObject
import com.anytypeio.anytype.domain.objects.DefaultObjectStore
import com.anytypeio.anytype.domain.objects.DefaultStoreOfRelations
import com.anytypeio.anytype.domain.objects.ObjectStore
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
import com.anytypeio.anytype.domain.objects.StoreOfRelations
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.DataViewObjectValueProvider
@ -59,6 +60,9 @@ class DisplayRelationNumberValueTest {
@Mock
lateinit var analytics: Analytics
@Mock
lateinit var storeOfObjectTypes: StoreOfObjectTypes
@get:Rule
val animationsRule = DisableAnimationsRule()
@ -81,7 +85,8 @@ class DisplayRelationNumberValueTest {
),
values = DataViewObjectValueProvider(db = db, objectState = state),
reloadObject = reloadObject,
analytics = analytics
analytics = analytics,
storeOfObjectTypes = storeOfObjectTypes
)
}

View File

@ -52,6 +52,11 @@
<data android:scheme="anytype"
android:host="main" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".ui.settings.system.SettingsActivity"

View File

@ -3,6 +3,7 @@ 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.core_models.primitives.TypeKey
import com.anytypeio.anytype.di.feature.AddDataViewRelationObjectValueModule
import com.anytypeio.anytype.di.feature.AddDataViewRelationOptionValueModule
import com.anytypeio.anytype.di.feature.AddFileRelationModule
@ -87,6 +88,7 @@ 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
import com.anytypeio.anytype.di.feature.sharing.DaggerAddToAnytypeComponent
import com.anytypeio.anytype.di.feature.spaces.DaggerCreateSpaceComponent
import com.anytypeio.anytype.di.feature.spaces.DaggerSelectSpaceComponent
import com.anytypeio.anytype.di.feature.spaces.DaggerSpaceSettingsComponent
@ -100,6 +102,7 @@ import com.anytypeio.anytype.di.feature.wallpaper.WallpaperSelectModule
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetSourceModule
import com.anytypeio.anytype.di.feature.widgets.SelectWidgetTypeModule
import com.anytypeio.anytype.di.main.MainComponent
import com.anytypeio.anytype.presentation.objects.CreateObjectOfTypeViewModel
import com.anytypeio.anytype.ui.relations.RelationEditParameters
import com.anytypeio.anytype.ui.types.edit.TypeEditParameters
import com.anytypeio.anytype.ui.widgets.collection.DaggerCollectionComponent
@ -929,10 +932,13 @@ class ComponentManager(
.create(findComponentDependencies())
}
val createObjectOfTypeComponent = Component {
val createObjectOfTypeComponent = ComponentWithParams { excludedTypeKeys: List<TypeKey> ->
DaggerCreateObjectOfTypeComponent
.factory()
.create(findComponentDependencies())
.create(
params = CreateObjectOfTypeViewModel.Params(excludedTypeKeys),
dependencies = findComponentDependencies()
)
}
val appPreferencesComponent = Component {
@ -941,6 +947,11 @@ class ComponentManager(
.create(findComponentDependencies())
}
val addToAnytypeComponent = Component {
DaggerAddToAnytypeComponent
.factory()
.create(findComponentDependencies())
}
class Component<T>(private val builder: () -> T) {

View File

@ -3,6 +3,7 @@ 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.search.SearchObjects
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.relations.add.AddFileRelationViewModel
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider
import com.anytypeio.anytype.presentation.relations.providers.ObjectRelationProvider.Companion.INTRINSIC_PROVIDER_TYPE
@ -36,8 +37,9 @@ object AddFileRelationModule {
@Named(INTRINSIC_PROVIDER_TYPE) relations: ObjectRelationProvider,
@Named(INTRINSIC_PROVIDER_TYPE) values: ObjectValueProvider,
searchObjects: SearchObjects,
urlBuilder: UrlBuilder
urlBuilder: UrlBuilder,
spaceManager: SpaceManager
): AddFileRelationViewModel.Factory = AddFileRelationViewModel.Factory(
relations, values, searchObjects, urlBuilder
relations, values, searchObjects, urlBuilder, spaceManager
)
}

View File

@ -1,6 +1,7 @@
package com.anytypeio.anytype.di.feature
import android.content.Context
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.repo.AuthRepository
@ -46,11 +47,13 @@ object AppPreferencesModule {
fun provideViewModelFactory(
copyFileToCacheDirectory: CopyFileToCacheDirectory,
getNetworkMode: GetNetworkMode,
setNetworkMode: SetNetworkMode
setNetworkMode: SetNetworkMode,
analytics: Analytics
): PreferencesViewModel.Factory = PreferencesViewModel.Factory(
copyFileToCacheDirectory = copyFileToCacheDirectory,
getNetworkMode = getNetworkMode,
setNetworkMode = setNetworkMode
setNetworkMode = setNetworkMode,
analytics = analytics
)
}
@ -58,4 +61,5 @@ interface AppPreferencesDependencies : ComponentDependencies {
fun context(): Context
fun dispatchers(): AppCoroutineDispatchers
fun authRepository(): AuthRepository
fun analytics(): Analytics
}

View File

@ -4,6 +4,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerModal
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.`object`.ReloadObject
import com.anytypeio.anytype.domain.objects.StoreOfObjectTypes
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
@ -39,12 +40,14 @@ object RelationTextValueModule {
@Named(INTRINSIC_PROVIDER_TYPE) relations: ObjectRelationProvider,
@Named(INTRINSIC_PROVIDER_TYPE) values: ObjectValueProvider,
reloadObject: ReloadObject,
analytics: Analytics
analytics: Analytics,
storeOfObjectTypes: StoreOfObjectTypes
) = RelationTextValueViewModel.Factory(
relations = relations,
values = values,
reloadObject = reloadObject,
analytics = analytics
analytics = analytics,
storeOfObjectTypes = storeOfObjectTypes
)
@JvmStatic
@ -77,12 +80,14 @@ object RelationDataViewTextValueModule {
@Named(DATA_VIEW_PROVIDER_TYPE) relations: ObjectRelationProvider,
@Named(DATA_VIEW_PROVIDER_TYPE) values: ObjectValueProvider,
reloadObject: ReloadObject,
analytics: Analytics
analytics: Analytics,
storeOfObjectTypes: StoreOfObjectTypes
) = RelationTextValueViewModel.Factory(
relations = relations,
values = values,
reloadObject = reloadObject,
analytics = analytics
analytics = analytics,
storeOfObjectTypes = storeOfObjectTypes
)
@JvmStatic

View File

@ -3,6 +3,7 @@ package com.anytypeio.anytype.di.feature
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.domain.account.AccountStatusChannel
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.account.InterceptAccountStatus
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.Logout
@ -87,13 +88,15 @@ object MainEntryModule {
pathProvider: PathProvider,
configStorage: ConfigStorage,
featuresConfigProvider: FeaturesConfigProvider,
metricsProvider: MetricsProvider
metricsProvider: MetricsProvider,
awaitAccountStartManager: AwaitAccountStartManager
): ResumeAccount = ResumeAccount(
repository = authRepository,
pathProvider = pathProvider,
configStorage = configStorage,
featuresConfigProvider = featuresConfigProvider,
metricsProvider = metricsProvider
metricsProvider = metricsProvider,
awaitAccountStartManager = awaitAccountStartManager
)
@JvmStatic
@ -146,13 +149,15 @@ object MainEntryModule {
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager
spaceManager: SpaceManager,
awaitAccountStartManager: AwaitAccountStartManager
): Logout = Logout(
repo = repo,
user = user,
config = provider,
dispatchers = dispatchers,
spaceManager = spaceManager
spaceManager = spaceManager,
awaitAccountStartManager = awaitAccountStartManager
)
@JvmStatic

View File

@ -6,6 +6,7 @@ import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.core_utils.tools.FeatureToggles
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.interactor.CheckAuthorizationStatus
import com.anytypeio.anytype.domain.auth.interactor.GetLastOpenedObject
import com.anytypeio.anytype.domain.auth.interactor.LaunchAccount
@ -75,7 +76,8 @@ object SplashModule {
configStorage: ConfigStorage,
spaceManager: SpaceManager,
metricsProvider: MetricsProvider,
userSettings: UserSettingsRepository
userSettings: UserSettingsRepository,
awaitAccountStartManager: AwaitAccountStartManager
): LaunchAccount = LaunchAccount(
repository = authRepository,
pathProvider = pathProvider,
@ -83,7 +85,8 @@ object SplashModule {
configStorage = configStorage,
spaceManager = spaceManager,
metricsProvider = metricsProvider,
settings = userSettings
settings = userSettings,
awaitAccountStartManager = awaitAccountStartManager
)
@JvmStatic
@ -192,4 +195,5 @@ interface SplashDependencies : ComponentDependencies {
fun spaceManager(): SpaceManager
fun spaceStatusWatcher(): SpaceDeletedStatusWatcher
fun localeProvider(): LocaleProvider
fun awaitAccountStartManager(): AwaitAccountStartManager
}

View File

@ -4,6 +4,7 @@ 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.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.account.DateHelper
import com.anytypeio.anytype.domain.account.RestoreAccount
import com.anytypeio.anytype.domain.auth.interactor.Logout
@ -64,13 +65,15 @@ object DeletedAccountModule {
provider: ConfigStorage,
dispatchers: AppCoroutineDispatchers,
user: UserSettingsRepository,
spaceManager: SpaceManager
spaceManager: SpaceManager,
awaitAccountStartManager: AwaitAccountStartManager
): Logout = Logout(
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers,
spaceManager = spaceManager
spaceManager = spaceManager,
awaitAccountStartManager = awaitAccountStartManager
)
@JvmStatic
@ -102,4 +105,5 @@ interface DeletedAccountDependencies : ComponentDependencies {
fun relationsSubscriptionManager(): RelationsSubscriptionManager
fun objectTypesSubscriptionManager(): ObjectTypesSubscriptionManager
fun spaceDeletedStatusWatcher(): SpaceDeletedStatusWatcher
fun awaitAccountStartManager(): AwaitAccountStartManager
}

View File

@ -10,6 +10,7 @@ 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.BindsInstance
import dagger.Component
import dagger.Module
@ -22,12 +23,14 @@ import dagger.Module
)
@PerScreen
interface CreateObjectOfTypeComponent {
fun inject(fragment: CreateObjectOfTypeFragment)
@Component.Factory
interface Builder {
fun create(dependencies: CreateObjectOfTypeDependencies): CreateObjectOfTypeComponent
interface Factory {
fun create(
@BindsInstance params: CreateObjectOfTypeViewModel.Params,
dependencies: CreateObjectOfTypeDependencies
): CreateObjectOfTypeComponent
}
fun inject(fragment: CreateObjectOfTypeFragment)
}
@Module

View File

@ -5,6 +5,7 @@ import com.anytypeio.anytype.CrashReporter
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.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.FeaturesConfigProvider
@ -62,4 +63,5 @@ interface OnboardingMnemonicLoginDependencies : ComponentDependencies {
fun relationsSubscriptionManager(): RelationsSubscriptionManager
fun spaceStatusWatcher(): SpaceDeletedStatusWatcher
fun localeProvider(): LocaleProvider
fun awaitAccountStartManager(): AwaitAccountStartManager
}

View File

@ -2,6 +2,7 @@ package com.anytypeio.anytype.di.feature.settings
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.interactor.Logout
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
@ -61,12 +62,14 @@ object LogoutWarningModule {
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager
spaceManager: SpaceManager,
awaitAccountStartManager: AwaitAccountStartManager
): Logout = Logout(
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers,
spaceManager = spaceManager
spaceManager = spaceManager,
awaitAccountStartManager = awaitAccountStartManager
)
}

View File

@ -2,6 +2,7 @@ package com.anytypeio.anytype.di.feature.settings
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerScreen
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.account.DeleteAccount
import com.anytypeio.anytype.domain.auth.interactor.Logout
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
@ -83,13 +84,15 @@ object ProfileModule {
provider: ConfigStorage,
user: UserSettingsRepository,
dispatchers: AppCoroutineDispatchers,
spaceManager: SpaceManager
spaceManager: SpaceManager,
awaitAccountStartManager: AwaitAccountStartManager
): Logout = Logout(
repo = repo,
config = provider,
user = user,
dispatchers = dispatchers,
spaceManager = spaceManager
spaceManager = spaceManager,
awaitAccountStartManager = awaitAccountStartManager
)
@JvmStatic

View File

@ -0,0 +1,58 @@
package com.anytypeio.anytype.di.feature.sharing
import androidx.lifecycle.ViewModelProvider
import com.anytypeio.anytype.analytics.base.Analytics
import com.anytypeio.anytype.core_utils.di.scope.PerDialog
import com.anytypeio.anytype.di.common.ComponentDependencies
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.UserSettingsRepository
import com.anytypeio.anytype.domain.library.StorelessSubscriptionContainer
import com.anytypeio.anytype.domain.misc.UrlBuilder
import com.anytypeio.anytype.domain.workspace.SpaceManager
import com.anytypeio.anytype.presentation.sharing.AddToAnytypeViewModel
import com.anytypeio.anytype.ui.sharing.SharingFragment
import dagger.Binds
import dagger.Component
import dagger.Module
@Component(
dependencies = [AddToAnytypeDependencies::class],
modules = [
AddToAnytypeModule::class,
AddToAnytypeModule.Declarations::class
]
)
@PerDialog
interface AddToAnytypeComponent {
@Component.Factory
interface Factory {
fun create(dependency: AddToAnytypeDependencies): AddToAnytypeComponent
}
fun inject(fragment: SharingFragment)
}
@Module
object AddToAnytypeModule {
@Module
interface Declarations {
@PerDialog
@Binds
fun factory(factory: AddToAnytypeViewModel.Factory): ViewModelProvider.Factory
}
}
interface AddToAnytypeDependencies : ComponentDependencies {
fun blockRepo(): BlockRepository
fun spaceManager(): SpaceManager
fun dispatchers(): AppCoroutineDispatchers
fun userSettings(): UserSettingsRepository
fun configStorage(): ConfigStorage
fun container(): StorelessSubscriptionContainer
fun urlBuilder(): UrlBuilder
fun awaitAccountStartedManager(): AwaitAccountStartManager
fun analytics(): Analytics
}

View File

@ -1,6 +1,7 @@
package com.anytypeio.anytype.di.main
import com.anytypeio.anytype.data.auth.repo.config.GatewayProvider
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.Gateway
@ -50,5 +51,10 @@ object ConfigModule {
SupervisorJob() + Dispatchers.Default
)
@JvmStatic
@Provides
@Singleton
fun awaitAccountStartedManager(): AwaitAccountStartManager = AwaitAccountStartManager.Default
const val DEFAULT_APP_COROUTINE_SCOPE = "Default application coroutine scope"
}

View File

@ -36,6 +36,7 @@ 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.sharing.AddToAnytypeDependencies
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,8 +104,8 @@ interface MainComponent :
SpaceSettingsDependencies,
CreateObjectOfTypeDependencies,
SpacesStorageDependencies,
AppPreferencesDependencies
{
AppPreferencesDependencies,
AddToAnytypeDependencies {
fun inject(app: AndroidApplication)
@ -275,4 +276,9 @@ private abstract class ComponentDependenciesModule private constructor() {
@IntoMap
@ComponentDependenciesKey(AppPreferencesDependencies::class)
abstract fun providePreferencesDependencies(component: MainComponent): ComponentDependencies
@Binds
@IntoMap
@ComponentDependenciesKey(AddToAnytypeDependencies::class)
abstract fun provideAddToAnytypeDependencies(component: MainComponent): ComponentDependencies
}

View File

@ -614,7 +614,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
.onEach {
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onAddNewDocumentClicked(it.uniqueKey)
vm.onAddNewDocumentClicked(it)
}
}
dialog.show(childFragmentManager, "editor-create-object-of-type-dialog")
@ -842,7 +842,7 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
}
}
subscribe(vm.icon) { icon ->
binding.bottomToolbar.bind(icon)
if (hasBinding) binding.bottomToolbar.bind(icon)
}
}
}
@ -1036,12 +1036,10 @@ open class EditorFragment : NavigationFragment<FragmentEditorBinding>(R.layout.f
}
is Command.OpenObjectSelectTypeScreen -> {
hideKeyboard()
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onObjectTypeChanged(it)
dismiss()
}
}
val dialog = CreateObjectOfTypeFragment.newInstance(
excludedTypeKeys = command.excludedTypes,
onTypeSelected = vm::onObjectTypeChanged
)
dialog.show(childFragmentManager, null)
}
is Command.OpenMoveToScreen -> {

View File

@ -5,7 +5,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Build
import android.view.LayoutInflater
import android.widget.Button
import android.view.View
import android.widget.ProgressBar
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
@ -100,7 +100,12 @@ interface PickerDelegate : PickiTCallbacks {
}
override fun openFilePicker(mimeType: Mimetype, requestCode: Int?) {
permissionHelper.openFilePicker(mimeType, requestCode)
try {
permissionHelper.openFilePicker(mimeType, requestCode)
} catch (e: Throwable) {
Timber.e(e, "Error while opening file picker")
fragment.toast("Error while opening file picker")
}
}
override fun initPicker(ctx: Id) {
@ -188,7 +193,7 @@ interface PickerDelegate : PickiTCallbacks {
LayoutInflater.from(fragment.requireContext())
.inflate(R.layout.dialog_layout, null)
setView(view)
view.findViewById<Button>(R.id.btnCancel).setOnClickListener {
view.findViewById<View>(R.id.btnCancel).setOnClickListener {
pickiT.cancelTask()
if (pickitAlertDialog?.isShowing == true) {
pickitAlertDialog?.cancel()

View File

@ -94,7 +94,7 @@ class HomeScreenFragment : BaseComposeFragment() {
onClick = {
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onCreateNewObjectClicked(it.uniqueKey)
vm.onCreateNewObjectClicked(it)
dismiss()
}
}

View File

@ -31,6 +31,7 @@ import com.anytypeio.anytype.ui.relations.REQUEST_UNINSTALL_RELATION_ARG_ID
import com.anytypeio.anytype.ui.relations.REQUEST_UNINSTALL_RELATION_ARG_NAME
import com.anytypeio.anytype.ui.relations.RelationCreateFromScratchForObjectFragment
import com.anytypeio.anytype.ui.relations.RelationEditFragment
import com.anytypeio.anytype.ui.sets.ObjectSetFragment
import com.anytypeio.anytype.ui.settings.typography
import com.anytypeio.anytype.ui.spaces.SelectSpaceFragment
import com.anytypeio.anytype.ui.types.create.CreateObjectTypeFragment
@ -73,7 +74,7 @@ class LibraryFragment : BaseComposeFragment() {
onCreateObjectLongClicked = {
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onCreateObjectOfTypeClicked(it.uniqueKey)
vm.onCreateObjectOfTypeClicked(it)
}
}
dialog.show(childFragmentManager, "library-create-object-of-type-dialog")
@ -139,7 +140,7 @@ class LibraryFragment : BaseComposeFragment() {
R.id.pageSearchFragment
)
}
is LibraryViewModel.Navigation.CreateDoc -> {
is LibraryViewModel.Navigation.OpenEditor -> {
findNavController().safeNavigate(
R.id.libraryFragment,
R.id.objectNavigation,
@ -154,6 +155,16 @@ class LibraryFragment : BaseComposeFragment() {
args = SelectSpaceFragment.args(exitHomeWhenSpaceIsSelected = true)
)
}
is LibraryViewModel.Navigation.OpenSetOrCollection -> {
findNavController().safeNavigate(
R.id.libraryFragment,
R.id.dataViewNavigation,
bundleOf(
ObjectSetFragment.CONTEXT_ID_KEY to it.id
)
)
}
}
}
}

View File

@ -33,6 +33,7 @@ import com.anytypeio.anytype.presentation.main.MainViewModelFactory
import com.anytypeio.anytype.presentation.navigation.AppNavigation
import com.anytypeio.anytype.presentation.wallpaper.WallpaperColor
import com.anytypeio.anytype.ui.editor.CreateObjectFragment
import com.anytypeio.anytype.ui.sharing.SharingFragment
import com.anytypeio.anytype.ui_settings.appearance.ThemeApplicator
import com.github.javiersantos.appupdater.AppUpdater
import com.github.javiersantos.appupdater.enums.UpdateFrom
@ -106,6 +107,12 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
)
)
}
is Command.AddToAnytype -> {
SharingFragment.new(command.data).show(
supportFragmentManager,
SHARE_DIALOG_LABEL
)
}
is Command.Error -> {
toast(command.msg)
}
@ -114,6 +121,9 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
}
}
}
if (savedInstanceState == null && intent.action == Intent.ACTION_SEND) {
proceedWithShareIntent(intent)
}
}
private fun startAppUpdater() {
@ -147,20 +157,32 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
if (intent != null && intent.action == Intent.ACTION_VIEW) {
val data = intent.dataString
if (data != null && data.contains(DEEP_LINK_PATTERN)) {
deepLink = data
} else {
intent.extras?.getString(DefaultAppActionManager.ACTION_CREATE_NEW_TYPE_KEY)?.let {
vm.onIntentCreateObject(it)
if (intent != null) {
when(intent.action) {
Intent.ACTION_VIEW -> {
val data = intent.dataString
if (data != null && data.contains(DEEP_LINK_PATTERN)) {
deepLink = data
} else {
intent.extras?.getString(DefaultAppActionManager.ACTION_CREATE_NEW_TYPE_KEY)?.let {
vm.onIntentCreateObject(it)
}
}
}
Intent.ACTION_SEND -> {
proceedWithShareIntent(intent)
}
}
}
if (BuildConfig.DEBUG) {
Timber.d("on NewIntent: $intent")
}
}
private fun proceedWithShareIntent(intent: Intent) {
intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
vm.onIntentShare(it)
}
}
private fun setTheme(themeMode: ThemeMode) {
@ -226,5 +248,6 @@ class MainActivity : AppCompatActivity(R.layout.activity_main), AppNavigation.Pr
companion object {
const val AUTO_UPDATE_URL = "https://fra1.digitaloceanspaces.com/anytype-release/latest-android.json"
const val SHARE_DIALOG_LABEL = "anytype.dialog.share.label"
}
}

View File

@ -8,10 +8,14 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.primitives.TypeKey
import com.anytypeio.anytype.core_utils.ext.argOrNull
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
@ -25,6 +29,8 @@ class CreateObjectOfTypeFragment : BaseBottomSheetComposeFragment() {
@Inject
lateinit var factory: CreateObjectOfTypeViewModel.Factory
private val excludedTypeKeys get() = argOrNull<List<Key>>(EXCLUDED_TYPE_KEYS_ARG_KEY)
private val vm by viewModels<CreateObjectOfTypeViewModel> { factory }
lateinit var onTypeSelected: (ObjectWrapper.Type) -> Unit
@ -40,10 +46,13 @@ class CreateObjectOfTypeFragment : BaseBottomSheetComposeFragment() {
typography = typography
) {
CreateObjectOfTypeScreen(
views = vm.views.collectAsStateWithLifecycle().value,
state = vm.viewState.collectAsStateWithLifecycle().value,
onTypeClicked = vm::onTypeClicked,
onQueryChanged = vm::onQueryChanged,
onFocused = { expand() }
onFocused = {
skipCollapsed()
expand()
}
)
}
LaunchedEffect(Unit) {
@ -58,6 +67,7 @@ class CreateObjectOfTypeFragment : BaseBottomSheetComposeFragment() {
when (command) {
is Command.DispatchObjectType -> {
onTypeSelected(command.type)
dismiss()
}
is Command.ShowTypeInstalledToast -> {
toast(resources.getString(R.string.library_type_added, command.typeName))
@ -66,10 +76,29 @@ class CreateObjectOfTypeFragment : BaseBottomSheetComposeFragment() {
}
override fun injectDependencies() {
componentManager().createObjectOfTypeComponent.get().inject(this)
componentManager()
.createObjectOfTypeComponent.get(
params = excludedTypeKeys?.map { TypeKey(it) } ?: emptyList()
)
.inject(this)
}
override fun releaseDependencies() {
componentManager().createObjectOfTypeComponent.release()
}
companion object {
const val EXCLUDED_TYPE_KEYS_ARG_KEY = "arg.create-object-of-type.excluded-type-keys"
fun newInstance(
excludedTypeKeys: List<Key>,
onTypeSelected: (ObjectWrapper.Type) -> Unit
): CreateObjectOfTypeFragment = CreateObjectOfTypeFragment().apply {
this.onTypeSelected = onTypeSelected
arguments =
bundleOf(
EXCLUDED_TYPE_KEYS_ARG_KEY to excludedTypeKeys
)
}
}
}

View File

@ -69,13 +69,14 @@ 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
import com.anytypeio.anytype.presentation.objects.SelectTypeViewState
@Preview
@Composable
fun PreviewScreen() {
CreateObjectOfTypeScreen(
onTypeClicked = {},
views = emptyList(),
state = SelectTypeViewState.Loading,
onQueryChanged = {},
onFocused = {}
)
@ -86,7 +87,7 @@ fun CreateObjectOfTypeScreen(
onTypeClicked: (SelectTypeView.Type) -> Unit,
onQueryChanged: (String) -> Unit,
onFocused: () -> Unit,
views: List<SelectTypeView>
state: SelectTypeViewState
) {
Column(
modifier = Modifier.nestedScroll(rememberNestedScrollInteropConnection())
@ -96,40 +97,51 @@ fun CreateObjectOfTypeScreen(
Modifier
.align(Alignment.CenterHorizontally)
.padding(vertical = 6.dp)
.verticalScroll(rememberScrollState())
)
SearchField(
onQueryChanged = onQueryChanged,
onFocused = onFocused
)
Spacer(modifier = Modifier.height(8.dp))
ScreenContent(views, onTypeClicked)
ScreenContent(state, onTypeClicked)
}
}
@Composable
private fun ScreenContent(
views: List<SelectTypeView>,
state: SelectTypeViewState,
onTypeClicked: (SelectTypeView.Type) -> Unit
) {
if (views.isNotEmpty()) {
FlowRowContent(views, onTypeClicked)
}
AnimatedVisibility(
visible = views.isEmpty(),
enter = fadeIn(animationSpec = tween(500)),
exit = fadeOut(animationSpec = tween(500))
) {
Box(modifier = Modifier.fillMaxSize()) {
EmptyState(
modifier = Modifier.align(Alignment.Center),
title = stringResource(id = R.string.nothing_found),
description = stringResource(id = R.string.nothing_found_object_types),
icon = AlertConfig.Icon(
gradient = GRADIENT_TYPE_RED,
icon = R.drawable.ic_alert_error
)
)
when (state) {
is SelectTypeViewState.Content -> {
FlowRowContent(state.views, onTypeClicked)
}
SelectTypeViewState.Empty -> {
AnimatedVisibility(
visible = true,
enter = fadeIn(animationSpec = tween(500)),
exit = fadeOut(animationSpec = tween(500))
) {
Box(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
EmptyState(
modifier = Modifier.align(Alignment.Center),
title = stringResource(id = R.string.nothing_found),
description = stringResource(id = R.string.nothing_found_object_types),
icon = AlertConfig.Icon(
gradient = GRADIENT_TYPE_RED,
icon = R.drawable.ic_alert_error
)
)
}
}
}
SelectTypeViewState.Loading -> {}
}
}
@ -143,8 +155,7 @@ private fun FlowRowContent(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 20.dp)
.verticalScroll(rememberScrollState())
,
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
) {
@ -267,8 +278,7 @@ fun ObjectTypeItem(
shape = RoundedCornerShape(12.dp)
)
.clip(RoundedCornerShape(12.dp))
.clickable { onItemClicked() }
,
.clickable { onItemClicked() },
verticalAlignment = Alignment.CenterVertically
) {
Spacer(
@ -306,6 +316,7 @@ private fun SearchField(
modifier = Modifier
.height(48.dp)
.fillMaxWidth()
.verticalScroll(rememberScrollState())
) {
val focusManager = LocalFocusManager.current
val focusRequester = FocusRequester()
@ -356,8 +367,7 @@ private fun SearchField(
.onFocusChanged { state ->
if (state.isFocused)
onFocused()
}
,
},
maxLines = 1,
singleLine = true,
textStyle = BodyRegular.copy(
@ -374,7 +384,7 @@ private fun SearchField(
enabled = true,
placeholder = {
Text(
text = stringResource(R.string.search),
text = stringResource(R.string.search_hint),
style = BodyRegular
)
},
@ -405,9 +415,11 @@ private fun SearchField(
@Composable
private fun Section(title: String) {
Box(modifier = Modifier
.height(44.dp)
.fillMaxWidth()) {
Box(
modifier = Modifier
.height(44.dp)
.fillMaxWidth()
) {
Text(
modifier = Modifier
.align(Alignment.BottomStart),

View File

@ -37,6 +37,7 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.text.style.TextAlign
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.ColorMnemonicStub
import com.anytypeio.anytype.core_ui.ColorPagerIndicator
@ -50,6 +51,7 @@ import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.HeadlineOnBoardingDescription
import com.anytypeio.anytype.core_ui.views.PreviewTitle1Regular
import com.anytypeio.anytype.core_ui.views.UXBody
import com.anytypeio.anytype.ui.onboarding.screens.signin.MnemonicPhraseFormatter
@Composable
fun PagerIndicator(
@ -201,6 +203,45 @@ fun MnemonicPhraseWidgetPreview() {
)
}
@Composable
fun OnboardingMnemonicInput(
modifier: Modifier = Modifier,
text: MutableState<String>,
placeholder: String? = null,
singleLine: Boolean = true,
keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
keyboardActions: KeyboardActions = KeyboardActions()
) {
TextField(
modifier = modifier,
textStyle = UXBody
.copy(
lineHeight = 34.sp
)
,
value = text.value,
onValueChange = {
text.value = it
},
colors = TextFieldDefaults.outlinedTextFieldColors(
disabledBorderColor = Color.Transparent,
errorBorderColor = Color.Transparent,
focusedBorderColor = Color.Transparent,
unfocusedBorderColor = Color.Transparent,
cursorColor = ColorTextInputCursor
),
placeholder = {
placeholder?.let {
Text(text = it, style = UXBody.copy(color = ColorPlaceholderText))
}
},
singleLine = singleLine,
keyboardActions = keyboardActions,
keyboardOptions = keyboardOptions,
visualTransformation = MnemonicPhraseFormatter
)
}
@Composable
fun OnboardingInput(
modifier: Modifier = Modifier,
@ -215,9 +256,11 @@ fun OnboardingInput(
modifier = modifier.then(
Modifier
.background(
Color(0x26DAD7CA), RoundedCornerShape(24.dp)
color = Color(0x26DAD7CA),
shape = RoundedCornerShape(24.dp)
)
.height(68.dp)
.padding(horizontal = 8.dp)
),
textStyle = UXBody.copy(color = ColorTextInput),
value = text.value,

View File

@ -280,16 +280,22 @@ class OnboardingFragment : Fragment() {
}
) {
val focus = LocalFocusManager.current
val onBackClicked : () -> Unit = {
val lastDestination = navController.currentBackStackEntry
if (lastDestination?.destination?.route == OnboardingNavigation.setProfileName) {
focus.clearFocus(true)
navController.popBackStack()
} else {
Timber.d("Skipping exit click...")
}
}
currentPage.value = OnboardingPage.SET_PROFILE_NAME
backButtonCallback.value = {
focus.clearFocus(true)
navController.popBackStack()
}
SetProfileName(navController = navController)
BackHandler {
focus.clearFocus(true)
navController.popBackStack()
}
backButtonCallback.value = onBackClicked
SetProfileName(
navController = navController,
onBackClicked = onBackClicked
)
BackHandler { onBackClicked() }
}
}
}
@ -403,7 +409,8 @@ class OnboardingFragment : Fragment() {
@Composable
private fun SetProfileName(
navController: NavHostController
navController: NavHostController,
onBackClicked: () -> Unit
) {
val component = componentManager().onboardingSoulCreationComponent
val vm = daggerViewModel { component.get().getViewModel() }
@ -414,7 +421,7 @@ class OnboardingFragment : Fragment() {
SetProfileNameWrapper(
viewModel = vm,
onBackClicked = { navController.popBackStack() }
onBackClicked = onBackClicked
)
LaunchedEffect(Unit) {

View File

@ -1,12 +1,14 @@
package com.anytypeio.anytype.ui.onboarding.screens.signin
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
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.lazy.LazyColumn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Text
@ -16,6 +18,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.painterResource
@ -43,7 +46,7 @@ import com.anytypeio.anytype.core_ui.views.TitleLogin
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingMnemonicLoginViewModel
import com.anytypeio.anytype.presentation.onboarding.login.OnboardingMnemonicLoginViewModel.SetupState
import com.anytypeio.anytype.ui.onboarding.OnboardingInput
import com.anytypeio.anytype.ui.onboarding.OnboardingMnemonicInput
@Composable
fun RecoveryScreenWrapper(
@ -94,7 +97,7 @@ fun RecoveryScreen(
LazyColumn(
content = {
item {
OnboardingInput(
OnboardingMnemonicInput(
modifier = Modifier
.padding(
start = 18.dp,
@ -104,6 +107,14 @@ fun RecoveryScreen(
)
.height(165.dp)
.fillMaxWidth()
.background(
color = Color(0x26DAD7CA),
shape = RoundedCornerShape(24.dp)
)
.padding(
horizontal = 8.dp,
vertical = 4.dp
)
,
text = text,
singleLine = false,
@ -122,8 +133,7 @@ fun RecoveryScreen(
context.toast(emptyRecoveryPhraseError)
}
}
),
visualTransformation = MnemonicPhraseFormatter
)
)
}
item {

View File

@ -3,7 +3,6 @@ package com.anytypeio.anytype.ui.onboarding.screens.signup
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@ -122,7 +121,6 @@ fun SetProfileNameTitle(modifier: Modifier) {
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun SetProfileNameInput(
text: MutableState<String>,

View File

@ -1,22 +1,34 @@
package com.anytypeio.anytype.ui.relations
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.view.updateLayoutParams
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_utils.ext.withParent
import com.anytypeio.anytype.core_utils.ui.BaseDialogFragment
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetFragment
import com.anytypeio.anytype.databinding.FragmentRelationFileValueActionBinding
class FileActionsFragment : BaseDialogFragment<FragmentRelationFileValueActionBinding>() {
class FileActionsFragment : BaseBottomSheetFragment<FragmentRelationFileValueActionBinding>() {
override fun injectDependencies() {}
override fun releaseDependencies() {}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
sheet?.apply {
setBackgroundResource(android.R.color.transparent)
updateLayoutParams<CoordinatorLayout.LayoutParams> {
setMargins(
resources.getDimensionPixelSize(R.dimen.dp_8),
0,
resources.getDimensionPixelSize(R.dimen.dp_8),
resources.getDimensionPixelSize(R.dimen.dp_102)
)
}
}
binding.btnAdd.setOnClickListener {
withParent<FileActionReceiver> { onAddAction() }
dismiss()
@ -31,20 +43,6 @@ class FileActionsFragment : BaseDialogFragment<FragmentRelationFileValueActionBi
}
}
override fun onStart() {
super.onStart()
setupAppearance()
}
private fun setupAppearance() {
dialog?.window?.apply {
setGravity(Gravity.BOTTOM)
setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
setBackgroundDrawableResource(android.R.color.transparent)
setWindowAnimations(R.style.DefaultBottomDialogAnimation)
}
}
override fun inflateBinding(
inflater: LayoutInflater,
container: ViewGroup?

View File

@ -114,7 +114,8 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragm
vm.onObjectClicked(
ctx = ctx,
id = o.id,
layout = o.layout
layout = o.layout,
profileLinkIdentity = o.profileLinkIdentity
)
} else {
vm.onNonExistentObjectClicked(
@ -160,6 +161,15 @@ abstract class RelationValueBaseFragment<T: ViewBinding> : BaseBottomSheetFragm
jobs += lifecycleScope.subscribe(vm.copyFileStatus) { command ->
pickerDelegate.onCopyFileCommand(command)
}
jobs += lifecycleScope.subscribe(vm.isReadOnlyValue) { isReadOnly ->
if (isReadOnly) {
btnAddValue.gone()
btnEditOrDone.gone()
} else {
btnAddValue.visible()
btnEditOrDone.visible()
}
}
super.onStart()
vm.onStart(
ctx = ctx,

View File

@ -56,12 +56,14 @@ class AddFileRelationFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
skipCollapsed()
setFullHeightSheet()
binding.rvFiles.layoutManager = LinearLayoutManager(requireContext())
binding.rvFiles.adapter = adapter
binding.btnAdd.setOnClickListener { vm.onActionButtonClicked() }
searchRelationInput = binding.searchBar.root.findViewById(R.id.filterInputField)
searchRelationInput.apply {
hint = getString(R.string.choose_options)
hint = getString(R.string.search_hint)
}
clearSearchText = binding.searchBar.root.findViewById(R.id.clearSearchText)
clearSearchText.setOnClickListener {
@ -71,6 +73,7 @@ class AddFileRelationFragment :
}
override fun onStart() {
expand()
jobs += lifecycleScope.subscribe(vm.viewsFiltered) { observeState(it) }
jobs += lifecycleScope.subscribe(vm.commands) { observeCommands(it) }
jobs += lifecycleScope.subscribe(searchRelationInput.textChanges())

View File

@ -315,7 +315,7 @@ open class ObjectSetFragment :
.onEach {
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onAddNewDocumentClicked(it.uniqueKey)
vm.onAddNewDocumentClicked(it)
}
}
dialog.show(childFragmentManager, "set-create-object-of-type-dialog")

View File

@ -164,6 +164,6 @@ class ProfileSettingsFragment : BaseBottomSheetComposeFragment() {
}
}
private const val PADDING_TOP = 54
private const val PADDING_TOP = 28
private const val SELECT_IMAGE_CODE = 1

View File

@ -0,0 +1,405 @@
package com.anytypeio.anytype.ui.sharing
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
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.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Divider
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Text
import androidx.compose.material3.DropdownMenu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.graphics.toColorInt
import coil.compose.rememberAsyncImagePainter
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_ui.foundation.noRippleClickable
import com.anytypeio.anytype.core_ui.views.BodyRegular
import com.anytypeio.anytype.core_ui.views.ButtonPrimary
import com.anytypeio.anytype.core_ui.views.ButtonSecondary
import com.anytypeio.anytype.core_ui.views.ButtonSize
import com.anytypeio.anytype.core_ui.views.Caption1Medium
import com.anytypeio.anytype.core_ui.views.TitleInter15
import com.anytypeio.anytype.presentation.sharing.AddToAnytypeViewModel.SpaceView
import com.anytypeio.anytype.presentation.spaces.SpaceIconView
@Preview
@Composable
fun AddToAnytypeScreenUrlPreview() {
AddToAnytypeScreen(
data = SharingData.Url("https://en.wikipedia.org/wiki/Walter_Benjamin"),
onCancelClicked = {},
onDoneClicked = {},
spaces = emptyList(),
onSelectSpaceClicked = {}
)
}
@Preview
@Composable
fun AddToAnytypeScreenNotePreview() {
AddToAnytypeScreen(
data = SharingData.Raw("The Work of Art in the Age of its Technological Reproducibility"),
onCancelClicked = {},
onDoneClicked = {},
spaces = emptyList(),
onSelectSpaceClicked = {}
)
}
@Composable
fun AddToAnytypeScreen(
spaces: List<SpaceView>,
data: SharingData,
onCancelClicked: () -> Unit,
onDoneClicked: (SaveAsOption) -> Unit,
onSelectSpaceClicked: (SpaceView) -> Unit
) {
var isSaveAsMenuExpanded by remember { mutableStateOf(false) }
val items = if (data is SharingData.Url)
listOf(SAVE_AS_NOTE, SAVE_AS_BOOKMARK)
else
listOf(SAVE_AS_NOTE)
var selectedIndex by remember {
mutableStateOf(
when(data) {
is SharingData.Url -> SAVE_AS_BOOKMARK
else -> SAVE_AS_NOTE
}
)
}
Column(modifier = Modifier.fillMaxWidth()) {
Header()
DataSection(data)
Box(
modifier = Modifier
.fillMaxWidth()
.height(76.dp)
.noRippleClickable { isSaveAsMenuExpanded = !isSaveAsMenuExpanded }
) {
Text(
text = stringResource(R.string.sharing_menu_save_as_section_name),
modifier = Modifier
.padding(top = 14.dp, start = 20.dp),
style = Caption1Medium,
color = colorResource(id = R.color.text_secondary)
)
Text(
text = if (selectedIndex == SAVE_AS_BOOKMARK)
stringResource(id = R.string.sharing_menu_save_as_bookmark_option)
else
stringResource(id = R.string.sharing_menu_save_as_note_option),
modifier = Modifier
.align(Alignment.BottomStart)
.padding(bottom = 14.dp, start = 20.dp),
style = BodyRegular,
color = colorResource(id = R.color.text_primary)
)
if (items.size > 1) {
DropdownMenu(
expanded = isSaveAsMenuExpanded,
onDismissRequest = { isSaveAsMenuExpanded = false },
modifier = Modifier.background(
color = colorResource(id = R.color.background_secondary)
)
) {
items.forEachIndexed { index, s ->
DropdownMenuItem(
onClick = {
selectedIndex = index
isSaveAsMenuExpanded = false
}
) {
when(s) {
SAVE_AS_BOOKMARK -> {
Text(
text = stringResource(id = R.string.sharing_menu_save_as_bookmark_option),
style = BodyRegular,
color = colorResource(id = R.color.text_primary)
)
}
SAVE_AS_NOTE -> {
Text(
text = stringResource(id = R.string.sharing_menu_save_as_note_option),
style = BodyRegular,
color = colorResource(id = R.color.text_primary)
)
}
else -> {
// Draw nothing
}
}
}
if (index != items.lastIndex) {
Divider(
thickness = 0.5.dp,
color = colorResource(id = R.color.shape_primary)
)
}
}
}
}
}
val selected = spaces.firstOrNull { it.isSelected }
if (selected != null) {
CurrentSpaceSection(
name = selected.obj.name.orEmpty(),
spaces = spaces,
onSelectSpaceClicked = onSelectSpaceClicked,
icon = selected.icon
)
} else {
CurrentSpaceSection(
name = stringResource(id = R.string.unknown),
spaces = spaces,
onSelectSpaceClicked = onSelectSpaceClicked
)
}
Spacer(modifier = Modifier.height(20.dp))
Buttons(onCancelClicked, onDoneClicked, selectedIndex)
}
}
@Composable
private fun DataSection(data: SharingData) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp)
.border(
width = 1.dp,
color = colorResource(id = R.color.shape_primary),
shape = RoundedCornerShape(10.dp)
)
) {
Text(
text = stringResource(R.string.sharing_menu_data),
style = Caption1Medium,
color = colorResource(id = R.color.text_secondary),
modifier = Modifier
.padding(
top = 10.dp,
start = 16.dp,
end = 16.dp
)
)
Text(
text = data.data,
style = BodyRegular,
color = colorResource(id = R.color.text_primary),
modifier = Modifier.padding(
top = 30.dp,
start = 16.dp,
end = 16.dp,
bottom = 10.dp
),
maxLines = 5
)
}
}
@Composable
private fun Buttons(
onCancelClicked: () -> Unit,
onDoneClicked: (SaveAsOption) -> Unit,
selectedIndex: Int
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(68.dp)
.padding(horizontal = 20.dp),
verticalAlignment = Alignment.CenterVertically
) {
ButtonSecondary(
onClick = onCancelClicked,
size = ButtonSize.Large,
text = stringResource(id = R.string.cancel),
modifier = Modifier.weight(1.0f)
)
Spacer(modifier = Modifier.width(12.dp))
ButtonPrimary(
onClick = { onDoneClicked(selectedIndex) },
size = ButtonSize.Large,
text = stringResource(id = R.string.done),
modifier = Modifier.weight(1.0f)
)
}
}
@Composable
private fun CurrentSpaceSection(
icon: SpaceIconView? = null,
name: String,
spaces: List<SpaceView>,
onSelectSpaceClicked: (SpaceView) -> Unit
) {
var isSpaceSelectMenuExpanded by remember { mutableStateOf(false) }
Box(
modifier = Modifier
.fillMaxWidth()
.height(76.dp)
.noRippleClickable {
isSpaceSelectMenuExpanded = true
}
) {
Text(
text = stringResource(R.string.space),
modifier = Modifier
.padding(top = 14.dp, start = 20.dp),
style = Caption1Medium,
color = colorResource(id = R.color.text_secondary)
)
val hasIcon = icon is SpaceIconView.Gradient || icon is SpaceIconView.Image
if (icon != null && hasIcon) {
SmallSpaceIcon(
icon = icon,
modifier = Modifier
.padding(
start = 20.dp,
bottom = 17.dp
)
.align(Alignment.BottomStart)
)
}
Text(
text = name,
modifier = Modifier
.align(Alignment.BottomStart)
.padding(
bottom = 14.dp,
start = if (hasIcon) 44.dp else 20.dp
),
style = BodyRegular,
color = colorResource(id = R.color.text_primary)
)
DropdownMenu(
expanded = isSpaceSelectMenuExpanded,
onDismissRequest = { isSpaceSelectMenuExpanded = false },
modifier = Modifier.background(
color = colorResource(id = R.color.background_secondary)
)
) {
spaces.forEachIndexed { index, view ->
DropdownMenuItem(
onClick = {
onSelectSpaceClicked(view)
isSpaceSelectMenuExpanded = false
}
) {
Text(
text = view.obj.name.orEmpty(),
style = BodyRegular,
color = colorResource(id = R.color.text_primary)
)
}
if (index != spaces.lastIndex) {
Divider(
thickness = 0.5.dp,
color = colorResource(id = R.color.shape_primary)
)
}
}
}
}
}
@Composable
private fun Header() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(48.dp)
) {
Text(
text = stringResource(R.string.sharing_menu_add_to_anytype_header_title),
color = colorResource(id = R.color.text_primary),
modifier = Modifier.align(Alignment.Center),
style = TitleInter15
)
}
}
@Composable
private fun SmallSpaceIcon(
icon: SpaceIconView,
modifier: Modifier
) {
val size = 18.dp
when (icon) {
is SpaceIconView.Image -> {
Image(
painter = rememberAsyncImagePainter(
model = icon.url,
error = painterResource(id = com.anytypeio.anytype.ui_settings.R.drawable.ic_home_widget_space)
),
contentDescription = "Custom image space icon",
contentScale = ContentScale.Crop,
modifier = modifier
.size(size)
.clip(RoundedCornerShape(4.dp))
)
}
is SpaceIconView.Gradient -> {
val gradient = Brush.radialGradient(
colors = listOf(
Color(icon.from.toColorInt()),
Color(icon.to.toColorInt())
)
)
Box(
modifier = modifier
.size(size)
.clip(CircleShape)
.background(gradient)
)
}
else -> {
// Draw nothing.
}
}
}
const val SAVE_AS_NOTE = 0
const val SAVE_AS_BOOKMARK = 1
typealias SaveAsOption = Int
sealed class SharingData {
abstract val data: String
data class Url(val url: String) : SharingData() {
override val data: String
get() = url
}
data class Raw(val raw: String) : SharingData() {
override val data: String
get() = raw
}
}

View File

@ -0,0 +1,128 @@
package com.anytypeio.anytype.ui.sharing
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.URLUtil
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.core.os.bundleOf
import androidx.fragment.app.viewModels
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.fragment.findNavController
import com.anytypeio.anytype.R
import com.anytypeio.anytype.core_utils.ext.arg
import com.anytypeio.anytype.core_utils.ext.toast
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.anytypeio.anytype.di.common.componentManager
import com.anytypeio.anytype.presentation.home.OpenObjectNavigation
import com.anytypeio.anytype.presentation.sharing.AddToAnytypeViewModel
import com.anytypeio.anytype.ui.editor.EditorFragment
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
class SharingFragment : BaseBottomSheetComposeFragment() {
private val sharedData : SharingData get() {
val result = arg<String>(SHARING_DATE_KEY)
return if (URLUtil.isValidUrl(result)) {
SharingData.Url(result)
} else {
SharingData.Raw(result)
}
}
@Inject
lateinit var factory: AddToAnytypeViewModel.Factory
private val vm by viewModels<AddToAnytypeViewModel> { factory }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View = ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme(
typography = typography
) {
AddToAnytypeScreen(
data = sharedData,
onDoneClicked = { option ->
when(option) {
SAVE_AS_BOOKMARK -> vm.onCreateBookmark(url = sharedData.data)
SAVE_AS_NOTE -> vm.onCreateNote(sharedData.data)
}
},
onCancelClicked = {
vm.onCancelClicked().also {
dismiss()
}
},
spaces = vm.spaceViews.collectAsStateWithLifecycle().value,
onSelectSpaceClicked = { vm.onSelectSpaceClicked(it) }
)
LaunchedEffect(Unit) {
vm.navigation.collect { nav ->
when(nav) {
is OpenObjectNavigation.OpenEditor -> {
dismiss()
findNavController().navigate(
R.id.objectNavigation,
bundleOf(
EditorFragment.ID_KEY to nav.target
)
)
}
else -> {
// Do nothing.
}
}
}
}
LaunchedEffect(Unit) {
vm.toasts.collect { toast ->
toast(toast)
}
}
LaunchedEffect(Unit) {
vm.commands.collect { command ->
proceedWithCommand(command)
}
}
}
}
}
private fun proceedWithCommand(command: AddToAnytypeViewModel.Command) {
when (command) {
AddToAnytypeViewModel.Command.Dismiss -> {
dismiss()
}
is AddToAnytypeViewModel.Command.ObjectAddToSpaceToast -> {
val name = command.spaceName ?: resources.getString(R.string.untitled)
val msg = resources.getString(R.string.sharing_menu_toast_object_added, name)
toast(msg = msg)
}
}
}
override fun injectDependencies() {
componentManager().addToAnytypeComponent.get().inject(this)
}
override fun releaseDependencies() {
componentManager().addToAnytypeComponent.release()
}
companion object {
private const val SHARING_DATE_KEY = "arg.sharing.data-key"
fun new(data: String) : SharingFragment = SharingFragment().apply {
arguments = bundleOf(SHARING_DATE_KEY to data)
}
}
}

View File

@ -62,6 +62,7 @@ fun CreateSpaceScreen(
val input = remember {
mutableStateOf("")
}
val focusManager = LocalFocusManager.current
Box(
modifier = Modifier.fillMaxSize()
) {
@ -84,7 +85,13 @@ fun CreateSpaceScreen(
onSpaceIconClicked = onSpaceIconClicked
)
Spacer(modifier = Modifier.height(10.dp))
SpaceNameInput(input = input)
SpaceNameInput(
input = input,
onActionDone = {
focusManager.clearFocus()
onCreate(input.value)
}
)
Divider()
Section(title = stringResource(id = R.string.type))
TypeOfSpace(spaceType = PRIVATE_SPACE_TYPE)
@ -95,7 +102,10 @@ fun CreateSpaceScreen(
Spacer(modifier = Modifier.height(78.dp))
}
CreateSpaceButton(
onCreate = onCreate,
onCreate = { name ->
focusManager.clearFocus()
onCreate(name)
},
input = input,
modifier = Modifier.align(Alignment.BottomCenter),
isLoading = isLoading
@ -165,9 +175,9 @@ fun SpaceIcon(
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun SpaceNameInput(
input: MutableState<String>
input: MutableState<String>,
onActionDone: () -> Unit
) {
val focusManager = LocalFocusManager.current
val focusRequester = FocusRequester()
Box(
modifier = Modifier
@ -178,9 +188,7 @@ fun SpaceNameInput(
value = input.value,
onValueChange = { input.value = it },
keyboardActions = KeyboardActions(
onDone = {
focusManager.clearFocus()
}
onDone = { onActionDone() }
),
modifier = Modifier
.fillMaxWidth()

View File

@ -22,6 +22,7 @@ import com.anytypeio.anytype.presentation.spaces.Command
import com.anytypeio.anytype.presentation.spaces.SelectSpaceViewModel
import com.anytypeio.anytype.ui.settings.typography
import javax.inject.Inject
import timber.log.Timber
class SelectSpaceFragment : BaseBottomSheetComposeFragment() {
@ -84,10 +85,14 @@ class SelectSpaceFragment : BaseBottomSheetComposeFragment() {
findNavController().popBackStack()
}
is Command.SwitchToNewSpace -> {
if (exitHomeWhenSpaceIsSelected == true) {
findNavController().navigate(R.id.switchSpaceAction)
} else {
findNavController().popBackStack()
try {
if (exitHomeWhenSpaceIsSelected == true) {
findNavController().navigate(R.id.switchSpaceAction)
} else {
findNavController().popBackStack()
}
} catch (e: Exception) {
Timber.e(e, "Navigation error")
}
}
}

View File

@ -35,6 +35,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.rememberAsyncImagePainter
import com.anytypeio.anytype.R
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.Caption1Medium
@ -154,7 +155,9 @@ private fun SelectSpaceSpaceItem(
) {
SpaceImageBlock(
icon = item.view.icon,
onSpaceIconClick = { onSpaceClicked(item.view) },
onSpaceIconClick = throttledClick(
onClick = { onSpaceClicked(item.view) }
),
gradientBackground = colorResource(id = R.color.default_gradient_background),
gradientCornerRadius = 4.dp
)

View File

@ -71,7 +71,6 @@ class EditorTemplateFragment : EditorFragment() {
private fun initializeBinding() {
with(binding) {
root.background = null
if (fragmentType == TYPE_TEMPLATE_SELECT || fragmentType == TYPE_TEMPLATE_EDIT) {
recycler.updateLayoutParams<ConstraintLayout.LayoutParams> {
topMargin = dimen(R.dimen.default_toolbar_height)

View File

@ -57,7 +57,7 @@ class CollectionFragment : BaseComposeFragment() {
onCreateObjectLongClicked = {
val dialog = CreateObjectOfTypeFragment().apply {
onTypeSelected = {
vm.onAddClicked(it.uniqueKey)
vm.onAddClicked(it)
}
}
dialog.show(childFragmentManager, "fullscreen-widget-create-object-of-type-dialog")

View File

@ -134,7 +134,7 @@ fun ScreenContent(
backClick = { vm.onPrevClicked() },
homeClick = { vm.onHomeClicked() },
searchClick = { vm.onSearchClicked() },
addDocClick = { vm.onAddClicked() },
addDocClick = { vm.onAddClicked(null) },
onCreateObjectLongClicked = onCreateObjectLongClicked,
onProfileClicked = vm::onProfileClicked,
profileIcon = vm.icon.collectAsState().value

View File

@ -68,16 +68,6 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.anytypeio.anytype.core_ui.widgets.toolbar.ObjectTypesWidget
android:id="@+id/objectTypesToolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/background_primary"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.anytypeio.anytype.core_ui.widgets.toolbar.MarkupColorToolbarWidget
android:id="@+id/markupColorToolbar"
android:layout_width="0dp"

View File

@ -1,16 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--typography, buttons 05.04-->
<FrameLayout 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="match_parent">
android:layout_height="wrap_content">
<LinearLayout 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="match_parent"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="@dimen/dp_20"
android:background="@drawable/rounded_rectangle_data_view_action"
android:orientation="vertical">
@ -18,6 +15,7 @@
<TextView
android:id="@+id/btnAdd"
style="@style/TextView.UXStyle.Body"
android:textColor="@color/text_primary"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="52dp"
@ -29,8 +27,6 @@
android:id="@+id/divider2"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:background="@color/viewer_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -39,6 +35,7 @@
<TextView
android:id="@+id/btnUploadFromGallery"
style="@style/TextView.UXStyle.Body"
android:textColor="@color/text_primary"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="52dp"
@ -50,8 +47,6 @@
android:id="@+id/divider3"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:background="@color/viewer_divider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -60,6 +55,7 @@
<TextView
android:id="@+id/btnUploadFromStorage"
style="@style/TextView.UXStyle.Body"
android:textColor="@color/text_primary"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="52dp"

View File

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--typography, buttons 05.04-->
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"

View File

@ -1,62 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!--typography, buttons 05.04-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.anytypeio.anytype.ui.relations.add.AddFileRelationFragment">
<androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="64dp">
<View
android:id="@+id/dragger"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="@dimen/default_dragger_width"
android:layout_height="@dimen/default_dragger_height"
android:layout_marginTop="6dp"
android:background="@drawable/dragger" />
<include
android:id="@+id/searchBar"
layout="@layout/widget_search_view"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="wrap_content">
<View
android:id="@+id/dragger"
android:layout_width="@dimen/default_dragger_width"
android:layout_height="@dimen/default_dragger_height"
android:layout_marginTop="6dp"
android:background="@drawable/dragger"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
android:id="@+id/searchBar"
layout="@layout/widget_search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dragger" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFiles"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/dragger" />
app:layout_constraintTop_toBottomOf="@+id/searchBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvFiles"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/searchBar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
android:layout_weight="1" />
</LinearLayout>
<com.anytypeio.anytype.core_ui.widgets.ButtonPrimaryNumber
android:id="@+id/btnAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="20dp"
android:layout_gravity="bottom"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="10dp"
app:buttonTitle="@string/btn_apply_new_object"
android:layout_gravity="bottom">
</com.anytypeio.anytype.core_ui.widgets.ButtonPrimaryNumber>
</LinearLayout>
app:buttonTitle="@string/btn_add" />
</FrameLayout>

View File

@ -15,6 +15,16 @@ android {
buildConfigField ANYTYPE_CLIPBOARD_LABEL_TYPE, ANYTYPE_CLIPBOARD_LABEL, ANYTYPE_CLIPBOARD_LABEL_VALUE
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.clipboard'
}

View File

@ -391,7 +391,8 @@ data class Block(
* @param style style for a block to create
*/
data class Text(
val style: Style
val style: Style,
val text: String? = null
) : Prototype()
data class File(

View File

@ -9,3 +9,7 @@ data class NetworkModeConfig(
val userFilePath: String? = null,
val storedFilePath: String? = null
)
object NetworkModeConst {
const val NODE_STAGING_ID = "N9DU6hLkTAbvcpji3TCKPPd3UQWKGyzUxGmgJEyvhByqAjfD"
}

View File

@ -0,0 +1,12 @@
package com.anytypeio.anytype.core_models
enum class ObjectOrigin(val code: Int) {
NONE(0),
CLIPBOARD(1),
DRAG_AND_DROP(2),
IMPORT(3),
WEB_CLIPPER(4),
SHARING_EXTENSION(5),
USE_CASE(6),
BUILT_IN(7)
}

View File

@ -242,9 +242,13 @@ sealed class 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 iconImage: String? get() = getValue(Relations.ICON_IMAGE)
val iconOption: Double? by default
val targetSpaceId: String? by default
val spaceAccountStatus: SpaceStatus
get() {
val code = getValue<Double?>(Relations.SPACE_ACCOUNT_STATUS)

View File

@ -24,6 +24,7 @@ object Relations {
const val IS_HIDDEN = "isHidden"
const val LAST_OPENED_DATE = "lastOpenedDate"
const val LAST_MODIFIED_DATE = "lastModifiedDate"
const val LAST_USED_DATE = "lastUsedDate"
const val TYPE = "type"
const val LINKS = "links"
const val TARGET_OBJECT_TYPE = "targetObjectType"
@ -68,6 +69,8 @@ object Relations {
const val BACKLINKS = "backlinks"
const val ORIGIN = "origin"
/**
* Transitive relation key.
*/

View File

@ -43,4 +43,12 @@ fun Map<Id, Struct>.unset(
fun Struct.mapToObjectWrapperType(): ObjectWrapper.Type? =
if (containsKey(Relations.ID) && containsKey(Relations.UNIQUE_KEY)) ObjectWrapper.Type(this)
else null
else null
inline fun <reified T> Struct.getValues(key: String): List<T> {
return when (val value = getOrDefault(key, emptyList<T>())) {
is T -> listOf(value)
is List<*> -> value.typeOf()
else -> emptyList()
}
}

View File

@ -18,6 +18,16 @@ android {
viewBinding true
compose true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.core_ui'
}

View File

@ -298,9 +298,12 @@ fun SyncStatusView?.getLabelText(context: Context): String = when (this) {
SyncStatusView.Unknown -> context.getString(R.string.sync_status_unknown)
SyncStatusView.Offline -> context.getString(R.string.sync_status_offline)
SyncStatusView.Syncing -> context.getString(R.string.sync_status_syncing)
is SyncStatusView.Synced -> context.getString(R.string.sync_status_synced)
SyncStatusView.Failed -> context.getString(R.string.sync_status_failed)
SyncStatusView.IncompatibleVersion -> context.getString(R.string.sync_status_incompatible)
SyncStatusView.Synced.LocalOnly -> context.getString(R.string.sync_status_local_only)
SyncStatusView.Synced.AnyNetwork -> context.getString(R.string.sync_status_synced)
SyncStatusView.Synced.SelfHostedNetwork -> context.getString(R.string.sync_status_synced)
SyncStatusView.Synced.StagingNetwork -> context.getString(R.string.sync_status_synced)
else -> ""
}

View File

@ -1273,7 +1273,12 @@ class BlockAdapter(
item = blocks[position] as BlockView.DataView.Deleted
)
}
else -> throw IllegalStateException("Unexpected view holder: $holder")
is Unsupported -> {
holder.bind(item = blocks[position] as BlockView.Unsupported)
}
else -> {
Timber.e("Unexpected view holder: $holder")
}
}
checkIfDecorationChanged(holder, payloads.typeOf(), position)
}

View File

@ -4,6 +4,8 @@ import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.core_ui.R
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationCheckboxBinding
import com.anytypeio.anytype.core_ui.databinding.ItemRelationListRelationDefaultBinding
@ -18,7 +20,6 @@ import com.anytypeio.anytype.core_ui.widgets.RelationObjectItem
import com.anytypeio.anytype.core_ui.widgets.text.TagWidget
import com.anytypeio.anytype.core_utils.ext.gone
import com.anytypeio.anytype.core_utils.ext.visible
import com.anytypeio.anytype.core_models.ThemeColor
import com.anytypeio.anytype.presentation.relations.ObjectRelationView
import com.anytypeio.anytype.presentation.sets.model.ObjectView
@ -37,7 +38,12 @@ sealed class ListRelationViewHolder(
fun bind(item: ObjectRelationView) {
tvTitle.text = item.name
tvValue.apply {
text = item.value
if (item.key == Relations.ORIGIN) {
val code = item.value?.toInt() ?: -1
setText(code.resRelationOrigin())
} else {
text = item.value
}
if (item is ObjectRelationView.Default) {
when (item.format) {
Relation.Format.SHORT_TEXT -> setHint(R.string.enter_text)
@ -51,7 +57,7 @@ sealed class ListRelationViewHolder(
}
}
}
setLockIcon(tvTitle, item.readOnly)
setLockIcon(tvTitle, item)
}
}
@ -64,7 +70,7 @@ sealed class ListRelationViewHolder(
fun bind(item: ObjectRelationView.Checkbox) = with(itemView) {
tvTitle.text = item.name
ivCheckbox.isSelected = item.isChecked
setLockIcon(tvTitle, item.system)
setLockIcon(tvTitle, item)
}
}
@ -91,7 +97,7 @@ sealed class ListRelationViewHolder(
text = null
}
}
setLockIcon(tvTitle, item.system)
setLockIcon(tvTitle, item)
}
}
@ -108,7 +114,7 @@ sealed class ListRelationViewHolder(
} else {
placeholder.gone()
}
setLockIcon(tvTitle, item.system)
setLockIcon(tvTitle, item)
for (i in 0..MAX_VISIBLE_TAGS_INDEX) getViewByIndex(i)?.gone()
item.tags.forEachIndexed { index, tagView ->
when (index) {
@ -150,7 +156,7 @@ sealed class ListRelationViewHolder(
} else {
placeholder.gone()
}
setLockIcon(tvTitle, item.system)
setLockIcon(tvTitle, item)
for (i in 0..MAX_VISIBLE_OBJECTS_INDEX) getViewByIndex(i)?.gone()
item.objects.forEachIndexed { index, objectView ->
when (index) {
@ -196,7 +202,7 @@ sealed class ListRelationViewHolder(
} else {
placeholder.gone()
}
setLockIcon(tvTitle, item.system)
setLockIcon(tvTitle, item)
item.files.forEachIndexed { index, fileView ->
when (index) {
in 0..MAX_VISIBLE_FILES_INDEX -> {
@ -237,12 +243,26 @@ sealed class ListRelationViewHolder(
itemView.setBlockBackgroundColor(color)
}
fun setLockIcon(view: TextView, isReadOnly: Boolean) {
if (isReadOnly) {
fun setLockIcon(view: TextView, item: ObjectRelationView) {
if (item.readOnly) {
view.setCompoundDrawablesWithIntrinsicBounds(systemIconDrawable, null, null, null)
view.visible()
} else {
view.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null)
}
}
}
fun Int.resRelationOrigin() : Int {
return when(this) {
0 -> R.string.relation_origin_none
1 -> R.string.relation_origin_clipboard
2 -> R.string.relation_origin_dnd
3 -> R.string.relation_origin_imported_object
4 -> R.string.relation_origin_web_clipper
5 -> R.string.relation_origin_mobile_sharing_extension
6 -> R.string.relation_origin_use_case
7 -> R.string.relation_origin_library_installed
else -> R.string.unknown
}
}

View File

@ -320,8 +320,8 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
}
if (relation.value == null) {
view.alpha = 0.5f
view.setOnClickListener {
click(ListenerType.Relation.Featured(relation))
}
addView(view)
ids.add(view.id)
@ -339,8 +339,8 @@ class FeaturedRelationGroupWidget : ConstraintLayout {
maxLines = 1
ellipsize = TextUtils.TruncateAt.END
}
if (relation.value == null) {
view.alpha = 0.5f
view.setOnClickListener {
click(ListenerType.Relation.Featured(relation))
}
addView(view)
ids.add(view.id)

View File

@ -27,10 +27,6 @@ class StatusBadgeWidget @JvmOverloads constructor(
visible()
tint(color = context.color(R.color.palette_system_red))
}
is SyncStatusView.Synced -> {
visible()
tint(color = context.color(R.color.palette_system_green))
}
SyncStatusView.Syncing -> {
visible()
tint(color = context.color(R.color.palette_system_amber_100))
@ -38,6 +34,15 @@ class StatusBadgeWidget @JvmOverloads constructor(
SyncStatusView.Unknown, SyncStatusView.Offline, null -> {
gone()
}
SyncStatusView.Synced.LocalOnly -> {
gone()
}
SyncStatusView.Synced.AnyNetwork,
SyncStatusView.Synced.SelfHostedNetwork,
SyncStatusView.Synced.StagingNetwork -> {
visible()
tint(color = context.color(R.color.palette_system_green))
}
}
}
}

View File

@ -24,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
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.core_ui.R
@ -31,8 +32,30 @@ import com.anytypeio.anytype.core_ui.foundation.noRippleThrottledClickable
import com.anytypeio.anytype.core_ui.views.Caption1Medium
import com.anytypeio.anytype.emojifier.Emojifier
import com.anytypeio.anytype.presentation.editor.EditorViewModel
import com.anytypeio.anytype.presentation.objects.ObjectTypeView
@Preview(showBackground = true, apiLevel = 33)
@Composable
fun MyChooseTypeHorizontalWidget() {
val state = EditorViewModel.TypesWidgetState(
visible = true,
items = listOf(
EditorViewModel.TypesWidgetItem.Search,
EditorViewModel.TypesWidgetItem.Type(
item = ObjectTypeView(
emoji = "👍",
name = "Like",
id = "12312",
description = null,
key = "dd"
)
)
)
)
ChooseTypeHorizontalWidget(state = state, onTypeClicked = {})
}
@Composable
fun ChooseTypeHorizontalWidget(
state: EditorViewModel.TypesWidgetState,
@ -43,7 +66,8 @@ fun ChooseTypeHorizontalWidget(
modifier = Modifier
.height(52.dp)
.fillMaxWidth()
.background(color = colorResource(id = R.color.background_primary))
.background(color = colorResource(id = R.color.background_primary)),
contentAlignment = Alignment.CenterStart
) {
LazyRow(
contentPadding = PaddingValues(

View File

@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-11.25,0a11.25,11.25 0,1 1,22.5 0a11.25,11.25 0,1 1,-22.5 0"
android:strokeWidth="1.5"
android:fillColor="#00000000"
android:strokeColor="@color/glyph_inactive"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,12m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0"
android:fillColor="@color/glyph_button"/>
</vector>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_variant_empty" android:state_selected="false" />
<item android:drawable="@drawable/ic_variant_selected" android:state_selected="true" />
</selector>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/white" />
<solid android:color="@color/background_secondary" />
<corners android:radius="10dp" />
</shape>

View File

@ -34,7 +34,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="@string/select_objects"
android:text="@string/no_value"
android:visibility="gone"
android:paddingEnd="@dimen/dp_12"
app:layout_constraintBottom_toBottomOf="parent"

View File

@ -65,7 +65,7 @@
<TextView
android:id="@+id/fileSelectionIndex"
style="@style/SelectedRelationCircleBadgeStyle"
style="@style/RelationCircleBadgeStyle"
android:layout_width="24dp"
android:layout_height="24dp"
android:visibility="invisible"

View File

@ -27,12 +27,12 @@
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
app:checkboxSize="24dp"
app:emojiSize="28dp"
app:hasEmojiRounded12Background="true"
app:imageCornerRadius="@dimen/list_item_object_image_corner_radius"
app:imageSize="@dimen/dp_48"
app:initialTextSize="28sp"
app:checkboxSize="24dp"
app:imageCornerRadius="@dimen/list_item_object_image_corner_radius"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/btnRemoveObject"
app:layout_constraintTop_toTopOf="parent"
@ -40,37 +40,39 @@
tools:background="@drawable/circle_solid_default" />
<TextView
android:hint="@string/untitled"
android:id="@+id/tvTitle"
style="@style/TextView.ContentStyle.PreviewTitles.2.Medium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="13dp"
style="@style/TextView.ContentStyle.PreviewTitles.2.Medium"
android:ellipsize="end"
android:hint="@string/untitled"
android:maxLines="1"
android:singleLine="true"
app:layout_constraintBottom_toTopOf="@+id/tvSubtitle"
app:layout_constraintEnd_toStartOf="@+id/btnDragAndDropObject"
app:layout_constraintStart_toEndOf="@+id/iconWidget"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintVertical_chainStyle="packed"
app:layout_goneMarginEnd="0dp"
tools:text="Charlie Chaplin" />
<TextView
android:id="@+id/tvSubtitle"
style="@style/TextView.ContentStyle.Relations.2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:ellipsize="end"
android:maxLines="1"
android:singleLine="true"
style="@style/TextView.ContentStyle.Relations.2"
android:textColor="@color/text_secondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/btnDragAndDropObject"
app:layout_constraintStart_toEndOf="@+id/iconWidget"
app:layout_constraintTop_toBottomOf="@+id/tvTitle"
app:layout_constraintVertical_bias="0.5"
app:layout_goneMarginEnd="0dp"
tools:text="Actor" />

View File

@ -463,6 +463,14 @@
<item name="android:background">@drawable/ic_tag_selected_selector</item>
</style>
<style name="RelationCircleBadgeStyle" parent="TextView.UXStyle.Body">
<item name="android:textSize">14sp</item>
<item name="android:textColor">@color/button_text</item>
<item name="android:layout_gravity">center_vertical|end</item>
<item name="android:gravity">center</item>
<item name="android:background">@drawable/ic_variant_selector</item>
</style>
<style name="GridCellTagStyle" parent="TextView.ContentStyle.Relations.2">
<item name="android:background">@drawable/rect_dv_cell_tag_item</item>
<item name="android:singleLine">true</item>

View File

@ -12,6 +12,16 @@ android {
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.core_utils'
}

View File

@ -116,4 +116,23 @@ object MimeTypes {
"application/x-zip",
"application/octet-stream"
)
val MIME_EXTRA_IMAGE_VIDEO = arrayOf(
"video/mp4",
"video/3gpp",
"video/3gpp2",
"video/H261",
"video/H263",
"video/mpv",
"video/ogg",
"video/x-msvideo",
"image/jpeg",
"image/png",
"image/svg+xml",
"image/webp",
"image/gif",
"image/avif",
"image/apng",
"image/bmp"
)
}

View File

@ -41,6 +41,7 @@ import androidx.navigation.NavDirections
import androidx.recyclerview.widget.RecyclerView
import com.anytypeio.anytype.core_utils.const.FileConstants.REQUEST_FILE_SAF_CODE
import com.anytypeio.anytype.core_utils.const.FileConstants.REQUEST_MEDIA_CODE
import com.anytypeio.anytype.core_utils.const.MimeTypes.MIME_EXTRA_IMAGE_VIDEO
import com.anytypeio.anytype.core_utils.const.MimeTypes.MIME_EXTRA_YAML
import com.anytypeio.anytype.core_utils.ui.BaseBottomSheetComposeFragment
import com.google.android.material.bottomsheet.BottomSheetBehavior
@ -279,37 +280,51 @@ fun String.normalizeUrl(): String =
* https://app.clickup.com/t/2cbqneb
*/
fun Fragment.startFilePicker(mime: Mimetype, requestCode: Int? = null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mime.value
if (mime == Mimetype.MIME_YAML) {
putExtra(Intent.EXTRA_MIME_TYPES, MIME_EXTRA_YAML)
}
}
val code = if (mime == Mimetype.MIME_FILE_ALL) {
REQUEST_FILE_SAF_CODE
} else {
REQUEST_MEDIA_CODE
}
startActivityForResult(intent, requestCode ?: code)
} else {
val intent =
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
when (mime) {
Mimetype.MIME_IMAGE_AND_VIDEO -> startMediaPicker(mime, requestCode)
else -> {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mime.value
if (mime == Mimetype.MIME_YAML) {
putExtra(Intent.EXTRA_MIME_TYPES, MIME_EXTRA_YAML)
}
}
val code = if (mime == Mimetype.MIME_FILE_ALL) {
REQUEST_FILE_SAF_CODE
} else {
REQUEST_MEDIA_CODE
}
startActivityForResult(intent, requestCode ?: code)
} else {
Intent(Intent.ACTION_PICK, MediaStore.Video.Media.INTERNAL_CONTENT_URI)
val intent =
if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI)
} else {
Intent(Intent.ACTION_PICK, MediaStore.Video.Media.INTERNAL_CONTENT_URI)
}
intent.apply {
type = mime.value
action = Intent.ACTION_GET_CONTENT
putExtra("return-data", true)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivityForResult(intent, requestCode ?: REQUEST_MEDIA_CODE)
}
intent.apply {
type = mime.value
action = Intent.ACTION_GET_CONTENT
putExtra("return-data", true)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivityForResult(intent, requestCode ?: REQUEST_MEDIA_CODE)
}
}
private fun Fragment.startMediaPicker(mime: Mimetype, requestCode: Int? = null) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = mime.value
putExtra(Intent.EXTRA_MIME_TYPES, MIME_EXTRA_IMAGE_VIDEO)
}
startActivityForResult(intent, requestCode ?: REQUEST_MEDIA_CODE)
}
/**
* Use this class for picking images from external storage
*/

View File

@ -17,6 +17,16 @@ android {
}
includeDependenciesReport = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.crash_reporting'
}

View File

@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
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
@ -209,10 +208,12 @@ class BlockDataRepository(
override suspend fun createBookmarkObject(
space: Id,
url: Url
url: Url,
details: Struct
): Id = remote.createBookmarkObject(
space = space,
url = url
url = url,
details = details
)
override suspend fun fetchBookmarkObject(ctx: Id, url: Url) = remote.fetchBookmarkObject(

View File

@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
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
@ -72,7 +71,7 @@ interface BlockRemote {
suspend fun uploadBlock(command: Command.UploadBlock): Payload
suspend fun setupBookmark(command: Command.SetupBookmark): Payload
suspend fun createAndFetchBookmarkBlock(command: Command.CreateBookmark): Payload
suspend fun createBookmarkObject(space: Id, url: Url): Id
suspend fun createBookmarkObject(space: Id, url: Url, details: Struct): Id
suspend fun fetchBookmarkObject(ctx: Id, url: Url)
suspend fun undo(command: Command.Undo): Payload
suspend fun importUseCaseSkip(space: Id)

View File

@ -23,5 +23,14 @@ dependencies {
}
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.device'
}

View File

@ -0,0 +1,16 @@
package com.anytypeio.anytype.domain.account
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
interface AwaitAccountStartManager {
fun isStarted(): Flow<Boolean>
fun setIsStarted(isStarted: Boolean)
object Default: AwaitAccountStartManager {
private val isStarted = MutableStateFlow(false)
override fun isStarted(): Flow<Boolean> = isStarted
override fun setIsStarted(isStarted: Boolean) {
this.isStarted.value = isStarted
}
}
}

View File

@ -1,6 +1,7 @@
package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.base.Either
@ -25,7 +26,8 @@ class LaunchAccount @Inject constructor(
private val featuresConfigProvider: FeaturesConfigProvider,
private val spaceManager: SpaceManager,
private val metricsProvider: MetricsProvider,
private val settings: UserSettingsRepository
private val settings: UserSettingsRepository,
private val awaitAccountStartManager: AwaitAccountStartManager
) : BaseUseCase<String, BaseUseCase.None>(context) {
override suspend fun run(params: None) = try {
@ -57,6 +59,7 @@ class LaunchAccount @Inject constructor(
} else {
spaceManager.set(setup.config.space)
}
awaitAccountStartManager.setIsStarted(true)
Either.Right(setup.config.analytics)
}
} catch (e: Throwable) {

View File

@ -1,5 +1,6 @@
package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.AppCoroutineDispatchers
import com.anytypeio.anytype.domain.base.Interactor
@ -16,6 +17,7 @@ class Logout @Inject constructor(
private val config: ConfigStorage,
private val user: UserSettingsRepository,
private val spaceManager: SpaceManager,
private val awaitAccountStartManager: AwaitAccountStartManager,
dispatchers: AppCoroutineDispatchers,
) : Interactor<Logout.Params>(context = dispatchers.io) {
@ -24,6 +26,7 @@ class Logout @Inject constructor(
user.clear()
config.clear()
spaceManager.clear()
awaitAccountStartManager.setIsStarted(false)
}
class Params(

View File

@ -2,6 +2,7 @@ package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.config.ConfigStorage
@ -17,7 +18,8 @@ class ResumeAccount(
private val pathProvider: PathProvider,
private val configStorage: ConfigStorage,
private val featuresConfigProvider: FeaturesConfigProvider,
private val metricsProvider: MetricsProvider
private val metricsProvider: MetricsProvider,
private val awaitAccountStartManager: AwaitAccountStartManager
) : BaseUseCase<Id, BaseUseCase.None>() {
override suspend fun run(params: None) = proceedWithResuming()
@ -40,7 +42,7 @@ class ResumeAccount(
networkMode = networkMode.networkMode,
networkConfigFilePath = networkMode.storedFilePath
)
repository.selectAccount(command).let { setup ->
val result = repository.selectAccount(command).let { setup ->
featuresConfigProvider.set(
enableDataView = setup.features.enableDataView ?: false,
enableDebug = setup.features.enableDebug ?: false,
@ -50,5 +52,7 @@ class ResumeAccount(
configStorage.set(config = setup.config)
setup.account.id
}
awaitAccountStartManager.setIsStarted(true)
result
}
}

View File

@ -3,6 +3,7 @@ package com.anytypeio.anytype.domain.auth.interactor
import com.anytypeio.anytype.core_models.AccountStatus
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.config.ConfigStorage
@ -17,7 +18,8 @@ class SelectAccount @Inject constructor(
private val repository: AuthRepository,
private val configStorage: ConfigStorage,
private val featuresConfigProvider: FeaturesConfigProvider,
private val metricsProvider: MetricsProvider
private val metricsProvider: MetricsProvider,
private val awaitAccountStartManager: AwaitAccountStartManager
) : BaseUseCase<StartAccountResult, SelectAccount.Params>() {
override suspend fun run(params: Params) = safe {
@ -46,6 +48,7 @@ class SelectAccount @Inject constructor(
enableSpaces = setup.features.enableSpaces ?: false
)
configStorage.set(config = setup.config)
awaitAccountStartManager.setIsStarted(true)
StartAccountResult(setup.config.analytics, setup.status)
}

View File

@ -9,7 +9,6 @@ import com.anytypeio.anytype.core_models.DVFilter
import com.anytypeio.anytype.core_models.DVSort
import com.anytypeio.anytype.core_models.DVViewer
import com.anytypeio.anytype.core_models.DVViewerType
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
@ -127,7 +126,7 @@ interface BlockRepository {
/**
* Creates bookmark object from url and returns its id.
*/
suspend fun createBookmarkObject(space: Id, url: Url): Id
suspend fun createBookmarkObject(space: Id, url: Url, details: Struct): Id
suspend fun fetchBookmarkObject(ctx: Id, url: Url)

View File

@ -6,8 +6,10 @@ import com.anytypeio.anytype.core_models.DVFilterCondition
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.Key
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Relation
import com.anytypeio.anytype.core_models.RelationFormat
import com.anytypeio.anytype.core_models.Relations
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
@ -68,10 +70,9 @@ class CreateDataViewObject @Inject constructor(
}
is Params.Collection -> {
val command = Command.CreateObject(
template = params.templateId,
prefilled = resolveSetByRelationPrefilledObjectData(
filters = emptyList(),
relations = emptyList()
template = params.template,
prefilled = resolveCollectionPrefilledObjectData(
filters = params.filters
),
internalFlags = listOf(InternalFlags.ShouldSelectTemplate),
space = space,
@ -91,8 +92,8 @@ class CreateDataViewObject @Inject constructor(
filters: List<DVFilter>
): Struct = buildMap {
filters.forEach { filter ->
val relation = storeOfRelations.getByKey(filter.relation)
if (relation != null && relation.isReadOnly == false) {
val relation = storeOfRelations.getByKey(filter.relation) ?: return@forEach
if (relation.isCanBeAddedToObject()) {
if (filter.condition == DVFilterCondition.ALL_IN || filter.condition == DVFilterCondition.IN || filter.condition == DVFilterCondition.EQUAL) {
filter.value?.let { put(filter.relation, it) }
}
@ -130,6 +131,23 @@ class CreateDataViewObject @Inject constructor(
emptyMap()
}
private suspend fun resolveCollectionPrefilledObjectData(
filters: List<DVFilter>
): Struct = buildMap {
filters.forEach { filter ->
val relation = storeOfRelations.getByKey(filter.relation) ?: return@forEach
if (relation.isCanBeAddedToObject()) {
if (
filter.condition == DVFilterCondition.ALL_IN
|| filter.condition == DVFilterCondition.IN
|| filter.condition == DVFilterCondition.EQUAL
) {
filter.value?.let { put(filter.relation, it) }
}
}
}
}
private fun resolveDefaultValueByFormat(format: RelationFormat): Any? {
when (format) {
Relation.Format.LONG_TEXT,
@ -168,7 +186,8 @@ class CreateDataViewObject @Inject constructor(
data class Collection(
val type: TypeKey,
val templateId: Id?
val filters: List<DVFilter>,
val template: Id?
) : Params()
}
@ -181,4 +200,8 @@ class CreateDataViewObject @Inject constructor(
companion object {
const val EMPTY_STRING_VALUE = ""
}
}
private fun ObjectWrapper.Relation.isCanBeAddedToObject(): Boolean {
return !isReadonlyValue && !Relations.systemRelationKeys.contains(key)
}

View File

@ -1,26 +1,30 @@
package com.anytypeio.anytype.domain.objects
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.Url
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import javax.inject.Inject
/**
* Use-case for creating bookmark object from url.
*/
class CreateBookmarkObject(
class CreateBookmarkObject @Inject constructor(
private val repo: BlockRepository
) : BaseUseCase<Id, CreateBookmarkObject.Params>() {
override suspend fun run(params: Params) = safe {
repo.createBookmarkObject(
space = params.space,
url = params.url
url = params.url,
details = params.details
)
}
data class Params(
val space: Id,
val url: Url
val url: Url,
val details: Struct = emptyMap()
)
}

View File

@ -0,0 +1,51 @@
package com.anytypeio.anytype.domain.objects
import com.anytypeio.anytype.core_models.Block
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.NO_VALUE
import com.anytypeio.anytype.core_models.ObjectTypeUniqueKeys
import com.anytypeio.anytype.core_models.Position
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.primitives.SpaceId
import com.anytypeio.anytype.core_models.primitives.TypeKey
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 CreatePrefilledNote @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
) : ResultInteractor<CreatePrefilledNote.Params, Id>(dispatchers.io) {
override suspend fun doWork(params: Params): Id {
val obj = repo.createObject(
Command.CreateObject(
typeKey = TypeKey(ObjectTypeUniqueKeys.NOTE),
space = SpaceId(params.space),
template = null,
internalFlags = emptyList(),
prefilled = params.details
)
)
repo.create(
command = Command.Create(
context = obj.id,
prototype = Block.Prototype.Text(
style = Block.Content.Text.Style.P,
text = params.text
),
position = Position.NONE,
target = NO_VALUE
)
)
return obj.id
}
data class Params(
val space: Id,
val text: String,
val details: Struct
)
}

View File

@ -3,6 +3,7 @@ package com.anytypeio.anytype.domain.page
import com.anytypeio.anytype.core_models.Command
import com.anytypeio.anytype.core_models.Id
import com.anytypeio.anytype.core_models.InternalFlags
import com.anytypeio.anytype.core_models.ObjectWrapper
import com.anytypeio.anytype.core_models.Payload
import com.anytypeio.anytype.core_models.Struct
import com.anytypeio.anytype.core_models.primitives.SpaceId
@ -66,7 +67,8 @@ class CreateObject @Inject constructor(
objectId = result.id,
event = result.event,
appliedTemplate = template,
typeKey = typeKey
typeKey = typeKey,
obj = ObjectWrapper.Basic(result.details)
)
}
@ -81,6 +83,7 @@ class CreateObject @Inject constructor(
val objectId: Id,
val event: Payload,
val appliedTemplate: String? = null,
val typeKey: TypeKey
val typeKey: TypeKey,
val obj: ObjectWrapper.Basic
)
}

View File

@ -0,0 +1,60 @@
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.DVSort
import com.anytypeio.anytype.core_models.DVSortType
import com.anytypeio.anytype.core_models.ObjectType
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.base.ResultInteractor
import com.anytypeio.anytype.domain.block.repo.BlockRepository
import javax.inject.Inject
class GetSpaceViews @Inject constructor(
private val repo: BlockRepository,
dispatchers: AppCoroutineDispatchers
): ResultInteractor<Unit, List<ObjectWrapper.SpaceView>>(dispatchers.io) {
override suspend fun doWork(params: Unit): List<ObjectWrapper.SpaceView> {
val result = repo.searchObjects(
keys = listOf(
Relations.ID,
Relations.TARGET_SPACE_ID,
Relations.NAME,
Relations.ICON_IMAGE,
Relations.ICON_OPTION,
Relations.SPACE_ACCOUNT_STATUS
),
filters = listOf(
DVFilter(
relation = Relations.LAYOUT,
value = ObjectType.Layout.SPACE_VIEW.code.toDouble(),
condition = DVFilterCondition.EQUAL
),
DVFilter(
relation = Relations.SPACE_ACCOUNT_STATUS,
value = SpaceStatus.SPACE_DELETED.code.toDouble(),
condition = DVFilterCondition.NOT_EQUAL
),
DVFilter(
relation = Relations.SPACE_LOCAL_STATUS,
value = SpaceStatus.OK.code.toDouble(),
condition = DVFilterCondition.EQUAL
)
),
sorts = listOf(
DVSort(
relationKey = Relations.LAST_OPENED_DATE,
type = DVSortType.DESC,
includeTime = true
)
),
limit = 0
)
return result.map {
ObjectWrapper.SpaceView(it)
}
}
}

View File

@ -1,29 +1,20 @@
package com.anytypeio.anytype.domain.auth
import com.anytypeio.anytype.core_models.CoroutineTestRule
import com.anytypeio.anytype.core_models.StubAccount
import com.anytypeio.anytype.core_models.StubAccountSetup
import com.anytypeio.anytype.core_models.StubConfig
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.interactor.ResumeAccount
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.BaseUseCase
import com.anytypeio.anytype.domain.config.ConfigStorage
import com.anytypeio.anytype.domain.config.FeaturesConfigProvider
import com.anytypeio.anytype.domain.device.PathProvider
import com.anytypeio.anytype.domain.platform.MetricsProvider
import com.anytypeio.anytype.domain.workspace.WorkspaceManager
import com.anytypeio.anytype.test_utils.MockDataFactory
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.stub
import org.mockito.kotlin.times
import org.mockito.kotlin.verifyBlocking
class ResumeAccountTest {
@ -49,6 +40,9 @@ class ResumeAccountTest {
@Mock
lateinit var metricsProvider: MetricsProvider
@Mock
lateinit var awaitAccountStartManager: AwaitAccountStartManager
lateinit var resumeAccount: ResumeAccount
private val config = StubConfig()
@ -61,7 +55,8 @@ class ResumeAccountTest {
configStorage = configStorage,
featuresConfigProvider = featuresConfigProvider,
pathProvider = pathProvider,
metricsProvider = metricsProvider
metricsProvider = metricsProvider,
awaitAccountStartManager = awaitAccountStartManager
)
}
}

View File

@ -9,6 +9,7 @@ import com.anytypeio.anytype.core_models.FeaturesConfig
import com.anytypeio.anytype.core_models.NetworkMode
import com.anytypeio.anytype.core_models.NetworkModeConfig
import com.anytypeio.anytype.core_models.StubConfig
import com.anytypeio.anytype.domain.account.AwaitAccountStartManager
import com.anytypeio.anytype.domain.auth.interactor.SelectAccount
import com.anytypeio.anytype.domain.auth.repo.AuthRepository
import com.anytypeio.anytype.domain.base.Either
@ -52,6 +53,9 @@ class StartAccountTest {
@Mock
lateinit var metricsProvider: MetricsProvider
@Mock
lateinit var awaitAccountStartManager: AwaitAccountStartManager
lateinit var selectAccount: SelectAccount
private val config = StubConfig()
@ -66,7 +70,8 @@ class StartAccountTest {
repository = repo,
configStorage = configStorage,
featuresConfigProvider = featuresConfigProvider,
metricsProvider = metricsProvider
metricsProvider = metricsProvider,
awaitAccountStartManager = awaitAccountStartManager
)
}

View File

@ -211,9 +211,9 @@ class GetObjectTypeTest {
}
private fun stubGetObjectTypes(types: List<ObjectWrapper.Type>) {
usecase.stub {
repo.stub {
onBlocking {
repo.searchObjects(
searchObjects(
filters = emptyList(),
keys = listOf(Relations.ID),
sorts = emptyList(),

View File

@ -1,29 +1,33 @@
[versions]
middlewareVersion = "v0.30.0-rc3"
kotlinVersion = '1.7.10'
middlewareVersion = "v0.30.3"
kotlinVersion = '1.8.22'
androidxCoreVersion = "1.10.1"
androidxCoreVersion = "1.12.0"
androidxComposeVersion = '1.5.0'
composeKotlinCompilerVersion = '1.3.1'
composeMaterial3Version = '1.1.1'
composeKotlinCompilerVersion = '1.4.8'
composeMaterial3Version = '1.1.2'
composeMaterialVersion = '1.5.0'
composeConstraintLayoutVersion = '1.0.1'
activityComposeVersion = '1.7.2'
dokkaVersion = '1.8.20'
activityComposeVersion = '1.8.1'
composeReorderableVersion = '0.9.6'
accompanistVersion = "0.30.0"
appcompatVersion = '1.6.1'
fragmentVersion = "1.6.1"
androidXAnnotationVersion = '1.7.0'
fragmentVersion = "1.6.2"
exoplayerVersion = "2.19.1"
wireVersion = "4.5.2"
glideVersion = "4.14.2"
mockitoKotlinVersion = "4.1.0"
mockitoKotlinVersion = "5.1.0"
junitVersion = '4.13.2'
androidJunitVersion = "1.1.4"
runnerVersion = "1.5.0"
mockitoAndroidVersion = '4.10.0'
kotlinCoroutinesVersion = '1.6.4'
coroutineTestingVersion = '1.6.4'
androidxTestCoreVersion = '1.5.0'
androidxCoreTestingVersion = '2.2.0'
androidxSecurityCryptoVersion = '1.0.0'
@ -33,10 +37,10 @@ recyclerviewVersion = '1.3.2'
cardviewVersion = '1.0.0'
emojiCompatVersion = '1.1.0'
viewPager2Version = '1.0.0'
lifecycleVersion = '2.6.1'
lifecycleRuntimeComposeVersion = '2.7.0-alpha01'
navigationVersion = '2.7.4'
navigationComposeVersion = '2.7.4'
lifecycleVersion = '2.6.2'
lifecycleRuntimeComposeVersion = '2.7.0-rc01'
navigationVersion = '2.7.5'
navigationComposeVersion = '2.7.5'
shimmerLayoutVersion = '0.5.0'
photoViewVersion = '2.3.0'
daggerVersion = '2.45'
@ -52,7 +56,6 @@ robolectricLatestVersion = '4.10.3'
kluentVersion = '1.14'
timberJunitVersion = '1.0.1'
turbineVersion = '0.12.1'
coroutineTestingVersion = '1.6.4'
liveDataTestingVersion = '1.2.0'
espressoVersion = '3.5.1'
disableAnimationVersion = '2.0.0'
@ -84,7 +87,7 @@ composeReorderable = { module = "org.burnoutcrew.composereorderable:reorderable"
composeConstraintLayout = { module = "androidx.constraintlayout:constraintlayout-compose", version.ref = "composeConstraintLayoutVersion" }
kotlinxSerializationJson = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version = "1.4.1" }
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompatVersion" }
androidAnnotations = { module = "androidx.annotation:annotation", version.ref = "appcompatVersion" }
androidAnnotations = { module = "androidx.annotation:annotation", version.ref = "androidXAnnotationVersion" }
design = { module = "com.google.android.material:material", version = "1.7.0" }
fragment = { module = "androidx.fragment:fragment-ktx", version.ref = "fragmentVersion" }
fragmentTesting = { module = "androidx.fragment:fragment-testing", version.ref = "fragmentVersion" }
@ -162,12 +165,12 @@ appUpdater = { module = "com.github.PLPsiSoft:AndroidAppUpdater", version = "991
[bundles]
[plugins]
application = { id = "com.android.application", version = "8.1.4" }
library = { id = "com.android.library", version = "8.1.4" }
application = { id = "com.android.application", version = "8.2.0" }
library = { id = "com.android.library", version = "8.2.0" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" }
dokka = { id = "org.jetbrains.dokka", version.ref = "kotlinVersion" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokkaVersion" }
kserialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinVersion" }
wire = { id = "com.squareup.wire", version = "4.4.3" }
firebaseDistribution = { id = "com.google.firebase.appdistribution", version = "3.1.1" }
firebaseDistribution = { id = "com.google.firebase.appdistribution", version = "4.0.1" }
kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlinVersion" }
gms = { id = "com.google.gms.google-services", version = "4.3.15" }
gms = { id = "com.google.gms.google-services", version = "4.4.0" }

View File

@ -1,5 +1,6 @@
#Thu Dec 14 17:20:55 CET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -16,5 +16,14 @@ dependencies {
}
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.emojifier'
}

View File

@ -42,7 +42,7 @@ object Emojifier {
try {
var result = search(unicode)
if (result == null) {
if (unicode.last() == SEPARATOR) {
if (unicode.lastOrNull() == SEPARATOR) {
val sb = StringBuilder()
unicode.forEachIndexed { index, char ->
if (index < unicode.length.dec()) sb.append(char)

View File

@ -7,6 +7,14 @@ android {
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.library_page_icon_picker_widget'
}

View File

@ -20,5 +20,13 @@ dependencies {
}
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
}
namespace 'com.anytypeio.anytype.library_syntax_highlighter'
}

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