Submit currently broken build process

This commit is contained in:
Paul Schaub 2020-04-22 23:12:14 +02:00
parent 7e1c9a7bdc
commit fc8f55e893
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
35 changed files with 3431 additions and 441 deletions

2399
Mercury-IM.ipr Normal file

File diff suppressed because it is too large Load Diff

493
Mercury-IM.iws Normal file
View File

@ -0,0 +1,493 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidLayouts">
<shared>
<config />
</shared>
</component>
<component name="ChangeListManager">
<list default="true" id="dba79dfb-7ac7-4943-9e44-ce0b4c5a028a" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/util/DebugUtils.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/domain/src/test/java/org/mercury_im/messenger/repository/TestAccountRepository.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/domain/src/test/java/org/mercury_im/messenger/util/ObservableList.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/domain/src/test/java/org/mercury_im/messenger/xmpp/MercuryConnectionManagerTest.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/raw/Account" afterDir="false" />
<change afterPath="$PROJECT_DIR$/raw/Conversation" afterDir="false" />
<change afterPath="$PROJECT_DIR$/raw/Messenger" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/app/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsFragment.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsFragment.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsRecyclerViewAdapter.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsRecyclerViewAdapter.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsViewModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/AccountsViewModel.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/app/src/test/java/org/mercury_im/messenger/ExampleUnitTest.java" beforeDir="false" afterPath="$PROJECT_DIR$/app/src/test/java/org/mercury_im/messenger/ExampleUnitTest.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/data/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/data/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/data/src/main/java/org/mercury_im/messenger/data/repository/XmppAccountRepository.java" beforeDir="false" afterPath="$PROJECT_DIR$/data/src/main/java/org/mercury_im/messenger/data/repository/XmppAccountRepository.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/build.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/domain/build.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/Messenger.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/Messenger.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccount.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccountUseCase.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/usecase/LogIntoAccount.java" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/usecase/RosterStoreBinder.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/store/RosterStoreBinder.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/util/Optional.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/util/Optional.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/MercuryConnection.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/MercuryConnection.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/MercuryConnectionManager.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/MercuryConnectionManager.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/XmppDirectMessageCenter.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/main/java/org/mercury_im/messenger/xmpp/XmppDirectMessageCenter.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/domain/src/test/java/org/mercury_im/messenger/learning_tests/smack/AddAccountUseCaseTest.java" beforeDir="false" afterPath="$PROJECT_DIR$/domain/src/test/java/org/mercury_im/messenger/learning_tests/smack/AddAccountUseCaseTest.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/entity/src/main/java/org/mercury_im/messenger/entity/IAccount.java" beforeDir="false" afterPath="$PROJECT_DIR$/entity/src/main/java/org/mercury_im/messenger/entity/IAccount.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/gradle/wrapper/gradle-wrapper.properties" beforeDir="false" afterPath="$PROJECT_DIR$/gradle/wrapper/gradle-wrapper.properties" afterDir="false" />
<change beforePath="$PROJECT_DIR$/libs/Smack" beforeDir="false" afterPath="$PROJECT_DIR$/libs/Smack" afterDir="false" />
<change beforePath="$PROJECT_DIR$/settings.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/settings.gradle" afterDir="false" />
<change beforePath="$PROJECT_DIR$/version.gradle" beforeDir="false" afterPath="$PROJECT_DIR$/version.gradle" afterDir="false" />
</list>
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CreatePatchCommitExecutor">
<option name="PATCH_PATH" value="" />
<option name="REVERSE_PATCH" value="false" />
</component>
<component name="DebuggerManager">
<breakpoint_any converted="true">
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
<breakpoint>
<option name="NOTIFY_CAUGHT" value="true" />
<option name="NOTIFY_UNCAUGHT" value="true" />
<option name="ENABLED" value="false" />
<option name="LOG_ENABLED" value="false" />
<option name="LOG_EXPRESSION_ENABLED" value="false" />
<option name="SUSPEND_POLICY" value="SuspendAll" />
<option name="COUNT_FILTER_ENABLED" value="false" />
<option name="COUNT_FILTER" value="0" />
<option name="CONDITION_ENABLED" value="false" />
<option name="CLASS_FILTERS_ENABLED" value="false" />
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
<option name="CONDITION" value="" />
<option name="LOG_MESSAGE" value="" />
</breakpoint>
</breakpoint_any>
<breakpoint_rules converted="true" />
<ui_properties converted="true" />
</component>
<component name="ExecutionTargetManager" SELECTED_TARGET="Pixel_3_API_29" />
<component name="ExternalProjectsData">
<projectState path="$PROJECT_DIR$">
<ProjectState />
</projectState>
</component>
<component name="ExternalProjectsManager">
<system id="GRADLE">
<state>
<task path="$PROJECT_DIR$/domain">
<activation />
</task>
<task path="$PROJECT_DIR$/data">
<activation />
</task>
<task path="$PROJECT_DIR$/app">
<activation />
</task>
<task path="$PROJECT_DIR$/entity">
<activation />
</task>
<task path="$PROJECT_DIR$/libs/Smack/smack-core">
<activation />
</task>
<task path="$PROJECT_DIR$/libs/Smack">
<activation />
</task>
<projects_view>
<tree_state>
<expand>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="app" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="app" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="app" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="build" type="c8890929:TasksNode$1" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="domain" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="domain" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Mercury-IM" type="2d1252cf:ModuleNode" />
<item name="domain" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="build" type="c8890929:TasksNode$1" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Smack" type="2d1252cf:ModuleNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Smack" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
</path>
<path>
<item name="" type="6a2764b6:ExternalProjectsStructure$RootNode" />
<item name="Mercury-IM" type="f1a62948:ProjectNode" />
<item name="Smack" type="2d1252cf:ModuleNode" />
<item name="Tasks" type="e4a08cd1:TasksNode" />
<item name="build" type="c8890929:TasksNode$1" />
</path>
</expand>
<select />
</tree_state>
</projects_view>
</state>
</system>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ModuleEditorState">
<option name="LAST_EDITED_MODULE_NAME" />
<option name="LAST_EDITED_TAB_NAME" />
</component>
<component name="ProjectId" id="1atyPPwblXwst2WB0Wi5Pj2sNso" />
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state />
</entry>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectReloadState">
<option name="STATE" value="0" />
</component>
<component name="PropertiesComponent">
<property name="GoToClass.includeLibraries" value="false" />
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
<property name="GoToFile.includeJavaFiles" value="false" />
<property name="MemberChooser.copyJavadoc" value="false" />
<property name="MemberChooser.showClasses" value="true" />
<property name="MemberChooser.sorted" value="false" />
<property name="project.structure.last.edited" value="Dependencies" />
<property name="project.structure.proportion" value="0.17" />
<property name="project.structure.side.proportion" value="0.2" />
</component>
<component name="PsdUISettings">
<option name="BUILD_VARIANTS_TAB" value="Flavors" />
<option name="LAST_EDITED_BUILD_TYPE" value="release" />
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager" selected="Gradle.Smack [build]">
<configuration default="true" type="JUnit" factoryName="JUnit">
<extension name="coverage" enabled="false" merge="false" />
<module name="" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" />
<option name="MAIN_CLASS_NAME" />
<option name="METHOD_NAME" />
<option name="TEST_OBJECT" value="class" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="moduleWithDependencies" />
</option>
<envs />
<method>
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="&lt;template&gt;" type="WebApp" default="true" selected="false">
<Host>localhost</Host>
<Port>5050</Port>
</configuration>
<configuration default="true" type="AndroidJUnit" factoryName="Android JUnit">
<option name="TEST_OBJECT" value="class" />
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration name="app" type="AndroidRunConfigurationType" factoryName="Android App" activateToolWindowBeforeRun="false">
<module name="app" />
<option name="DEPLOY" value="true" />
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
<option name="DEPLOY_AS_INSTANT" value="false" />
<option name="ARTIFACT_NAME" value="" />
<option name="PM_INSTALL_OPTIONS" value="" />
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
<option name="MODE" value="default_activity" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
<option name="SKIP_NOOP_APK_INSTALLATIONS" value="true" />
<option name="FORCE_STOP_RUNNING_APP" value="true" />
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="-1" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="DEBUGGER_TYPE" value="Auto" />
<Auto>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Auto>
<Hybrid>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Hybrid>
<Java />
<Native>
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
<option name="SHOW_STATIC_VARS" value="true" />
<option name="WORKING_DIR" value="" />
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
</Native>
<Profilers>
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Sample Java Methods" />
</Profilers>
<option name="DEEP_LINK" value="" />
<option name="ACTIVITY_CLASS" value="" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
<configuration default="true" type="Applet">
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
<method v="2">
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<method v="2">
<option name="BuildArtifacts" enabled="false" />
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="Mercury-IM:app [assemble]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/app" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="assemble" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
<configuration name="Smack [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/libs/Smack" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
<configuration name="Smack [clean]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/libs/Smack" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
<configuration name="Smack [jar]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/libs/Smack" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="jar" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
<configuration name="Smack:smack-core [build]" type="GradleRunConfiguration" factoryName="Gradle" temporary="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$/libs/Smack/smack-core" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
<method v="2" />
</configuration>
<configuration default="true" type="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
<option name="SHMEM_ADDRESS" value="javadebug" />
<option name="HOST" value="localhost" />
<option name="PORT" value="5005" />
<option name="AUTO_RESTART" value="false" />
<method v="2">
<option name="BuildArtifacts" enabled="false" />
</method>
</configuration>
<recent_temporary>
<list>
<item itemvalue="Gradle.Smack [build]" />
<item itemvalue="Gradle.Mercury-IM:app [assemble]" />
<item itemvalue="Gradle.Smack:smack-core [build]" />
<item itemvalue="Gradle.Smack [jar]" />
<item itemvalue="Gradle.Smack [clean]" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="dba79dfb-7ac7-4943-9e44-ce0b4c5a028a" name="Default Changelist" comment="" />
<created>1587569163841</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1587569163841</updated>
</task>
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="COLUMN_ORDER" />
</State>
</value>
</entry>
</map>
</option>
</component>
<component name="VcsManagerConfiguration">
<option name="OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT" value="true" />
<option name="MAKE_NEW_CHANGELIST_ACTIVE" value="true" />
</component>
<component name="XDebuggerManager">
<breakpoint-manager>
<default-breakpoints>
<breakpoint suspend="ALL" type="java-exception" />
</default-breakpoints>
</breakpoint-manager>
</component>
</project>

View File

@ -35,6 +35,7 @@ android {
dataBinding {
enabled true
}
buildToolsVersion = '29.0.2'
}
checkstyle {
@ -78,29 +79,29 @@ dependencies {
implementation project(":data")
implementation "io.requery:requery-android:$requeryVersion"
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61'
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.71'
// Dagger 2 for dependency injection
implementation "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
// ViewModel and LiveData
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
annotationProcessor "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
// Android extension for rxJava
api "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
// ButterKnife for View Binding
implementation "com.jakewharton:butterknife:$butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
implementation "com.jakewharton:butterknife:${butterKnifeVersion}"
annotationProcessor "com.jakewharton:butterknife-compiler:${butterKnifeVersion}"
// support libraries
implementation "androidx.appcompat:appcompat:$appCompatVersion"
implementation 'com.google.android.material:material:1.2.0-alpha03'
implementation "androidx.appcompat:appcompat:${appCompatVersion}"
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
implementation 'androidx.cardview:cardview:1.0.0'
@ -108,7 +109,7 @@ dependencies {
implementation 'androidx.recyclerview:recyclerview:1.1.0'
// circular image viewer for avatars
implementation 'de.hdodenhof:circleimageview:3.0.1'
implementation 'de.hdodenhof:circleimageview:3.1.0'
// Android specific classes of Smacks API
implementation "org.igniterealtime.smack:smack-android-extensions:$smackAndroidExtensionsVersion"

View File

@ -56,7 +56,7 @@ public class MercuryImApplication extends Application {
}
private void setupClientStateIndication() {
clientStateHandler.addClientStateListener(messenger);
clientStateHandler.addClientStateListener(messenger.getConnectionManager());
registerActivityLifecycleCallbacks(clientStateHandler);
}

View File

@ -49,11 +49,6 @@ public class AccountsFragment extends Fragment {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(AccountsViewModel.class);
this.adapter = new AccountsRecyclerViewAdapter(viewModel, accountClickListener);
}
@Override
public void onResume() {
super.onResume();
observeViewModel();
}

View File

@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.logging.Tags;
import org.mercury_im.messenger.ui.avatar.AvatarDrawable;
import org.mercury_im.messenger.ui.account.AccountsFragment.OnAccountListItemClickListener;
import org.mercury_im.messenger.util.AbstractDiffCallback;
@ -21,11 +22,15 @@ import org.mercury_im.messenger.xmpp.MercuryConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.android.schedulers.AndroidSchedulers;
public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRecyclerViewAdapter.ViewHolder> {
private static final Logger LOGGER = Logger.getLogger(Tags.TAG_ANDROID);
private final List<MercuryConnection> connections = new ArrayList<>();
private final OnAccountListItemClickListener onAccountClickListener;
private final AccountsViewModel viewModel;
@ -44,6 +49,7 @@ public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRe
}
public void setValues(List<MercuryConnection> values) {
LOGGER.log(Level.INFO, "AccountsRecyclerViewAdapter.setValues(" + values.size() + ")");
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(
new AccountsDiffCallback(values, connections), true);
connections.clear();

View File

@ -10,19 +10,24 @@ import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.Messenger;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.logging.Tags;
import org.mercury_im.messenger.util.DebugUtils;
import org.mercury_im.messenger.xmpp.MercuryConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable;
import lombok.Getter;
public class AccountsViewModel extends AndroidViewModel {
private static final Logger LOGGER = Logger.getLogger(Tags.TAG_ANDROID);
@Inject
AccountRepository repository;
@ -36,15 +41,20 @@ public class AccountsViewModel extends AndroidViewModel {
public AccountsViewModel(Application application) {
super(application);
MercuryImApplication.getApplication().getAppComponent().inject(this);
compositeDisposable.add(messenger.getConnectionManager()
.observeConnections()
.map(Map::values)
.subscribe(conns -> connections.postValue(new ArrayList<>(conns))));
compositeDisposable.add(repository.observeAllAccounts()
.map(accounts -> {
List<MercuryConnection> connections = new ArrayList<>(accounts.size());
for (Account account : accounts) {
connections.add(messenger.getConnectionManager().getOrCreateConnection(account));
}
return connections;
}).subscribe(connections::postValue));
}
@Override
protected void onCleared() {
super.onCleared();
LOGGER.log(Level.INFO, "AccountsViewModel.onCleared()");
compositeDisposable.clear();
}
@ -58,7 +68,7 @@ public class AccountsViewModel extends AndroidViewModel {
public void setAccountEnabled(Account accountModel, boolean enabled) {
accountModel.setEnabled(enabled);
repository.upsertAccount(accountModel)
.subscribe();
compositeDisposable.add(repository.upsertAccount(accountModel)
.subscribe());
}
}

View File

@ -17,6 +17,7 @@ import org.mercury_im.messenger.Messenger;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.entity.IAccount;
import org.mercury_im.messenger.logging.Tags;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -29,6 +30,8 @@ import io.reactivex.schedulers.Schedulers;
public class LoginViewModel extends AndroidViewModel {
private static final Logger LOGGER = Logger.getLogger(Tags.TAG_ANDROID);
private MutableLiveData<Error> usernameError = new MutableLiveData<>(new Error());
private MutableLiveData<Error> passwordError = new MutableLiveData<>(new Error());
private MutableLiveData<Boolean> loginButtonEnabled = new MutableLiveData<>(false);
@ -86,6 +89,8 @@ public class LoginViewModel extends AndroidViewModel {
Account account = new IAccount();
account.setAddress(username.asUnescapedString());
account.setPassword(password);
signalLoginSuccessful();
/*
disposable.add(messenger.addAccount()
.execute(account)
.subscribeOn(Schedulers.newThread())
@ -93,10 +98,11 @@ public class LoginViewModel extends AndroidViewModel {
.doOnComplete(this::signalLoginSuccessful)
.doOnError(this::signalLoginError)
.subscribe());
*/
}
private void signalLoginSuccessful() {
Logger.getAnonymousLogger().log(Level.INFO, "Signal Login Successful");
LOGGER.log(Level.INFO, "LoginViewModel.signalLoginSuccessful()");
loginCompleted.setValue(true);
}

View File

@ -1,8 +1,8 @@
package org.mercury_im.messenger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mercury_im.messenger.core.connection.ConnectionState;
import org.mercury_im.messenger.xmpp.MercuryConnection;
import org.mercury_im.messenger.xmpp.MercuryConnection.ConnectionState;
import io.reactivex.observers.TestObserver;
import io.reactivex.schedulers.TestScheduler;
@ -25,11 +25,11 @@ public class ExampleUnitTest {
@Test
public void test() {
TestScheduler testScheduler = new TestScheduler();
BehaviorSubject<ConnectionState> state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED);
BehaviorSubject<ConnectionState> state = BehaviorSubject.createDefault(ConnectionState.closed);
TestObserver<ConnectionState> observable = state.test();
assertEquals(ConnectionState.DISCONNECTED, state.getValue());
state.onNext(ConnectionState.CONNECTING);
assertEquals(ConnectionState.CONNECTING, state.getValue());
observable.assertValues(ConnectionState.DISCONNECTED, ConnectionState.CONNECTING).dispose();
assertEquals(ConnectionState.closed, state.getValue());
state.onNext(ConnectionState.connected);
assertEquals(ConnectionState.connected, state.getValue());
observable.assertValues(ConnectionState.connected, ConnectionState.closed).dispose();
}
}

View File

@ -1,5 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply plugin: 'idea'
buildscript {
repositories {
@ -7,7 +9,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:3.6.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -12,14 +12,15 @@ dependencies {
implementation project(":entity")
implementation project(':domain')
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"
// Dagger 2 for dependency injection
implementation "com.google.dagger:dagger:$daggerVersion"
compileOnly "com.google.dagger:dagger:$daggerVersion"
testCompileOnly "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
testAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
@ -31,6 +32,8 @@ dependencies {
testImplementation "junit:junit:$junitVersion"
testImplementation 'org.xerial:sqlite-jdbc:3.30.1'
implementation 'javax.inject:javax.inject:1'
}
sourceCompatibility = "8"

View File

@ -3,14 +3,16 @@ package org.mercury_im.messenger.data.repository;
import org.mercury_im.messenger.data.mapping.AccountMapping;
import org.mercury_im.messenger.data.model.AccountModel;
import org.mercury_im.messenger.data.repository.dao.AccountDao;
import org.mercury_im.messenger.util.Optional;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.util.Optional;
import org.mercury_im.messenger.util.ThreadUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Named;
@ -29,6 +31,9 @@ public class XmppAccountRepository
extends RequeryRepository
implements AccountRepository {
private static final Logger LOGGER = Logger.getLogger(XmppAccountRepository.class.getName());
private static final Level LEVEL = Level.INFO;
private final AccountMapping accountMapping;
private final AccountDao dao;
@ -48,6 +53,8 @@ public class XmppAccountRepository
.map(accountMapping::toModel)
.flatMap(dao::insert)
.map(model -> accountMapping.toEntity(model, account))
.doOnSuccess(a -> LOGGER.log(LEVEL, "insertAccount(" + account + "): onSuccess(): " + a))
.doOnError(e -> LOGGER.log(Level.SEVERE, "insertAccount(" + account + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -57,6 +64,9 @@ public class XmppAccountRepository
return dao.get(accountId).observableResult()
.map(result -> new Optional<>(result.firstOrNull()))
.map(accountMapping::toEntity)
.doOnNext(a -> LOGGER.log(LEVEL, "observeAccount(" + accountId + "): onNext(): " + a))
.doOnError(e -> LOGGER.log(Level.SEVERE, "observeAccount(" + accountId + "): onError()", e))
.doOnComplete(() -> LOGGER.log(LEVEL, "observeAccount(" + accountId + "): onComplete()"))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -65,6 +75,9 @@ public class XmppAccountRepository
public Maybe<Account> getAccount(UUID accountId) {
return dao.get(accountId).maybe()
.map(accountMapping::toEntity)
.doOnSuccess(a -> LOGGER.log(LEVEL, "getAccount(" + accountId + "): onSuccess(): " + a))
.doOnComplete(() -> LOGGER.log(LEVEL, "getAccount(" + accountId + "): onComplete()"))
.doOnError(e -> LOGGER.log(Level.SEVERE, "getAccount(" + accountId + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -74,6 +87,9 @@ public class XmppAccountRepository
return dao.get(address).observableResult()
.map(result -> new Optional<>(result.firstOrNull()))
.map(accountMapping::toEntity)
.doOnNext(o -> LOGGER.log(LEVEL, "observeAccountByAddress(" + address + "): onNext(): " + o))
.doOnError(e -> LOGGER.log(Level.SEVERE, "observeAccountByAddress(" + address + "): onError()", e))
.doOnComplete(() -> LOGGER.log(Level.INFO, "observeAccountByAddress(" + address + "): onComplete()"))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -82,6 +98,9 @@ public class XmppAccountRepository
public Maybe<Account> getAccountByAddress(String address) {
return dao.get(address).maybe()
.map(accountMapping::toEntity)
.doOnSuccess(a -> LOGGER.log(LEVEL, "getAccountByAddress(" + address + "): onSuccess(): " + a))
.doOnComplete(() -> LOGGER.log(LEVEL, "getAccountByAddress(" + address + "): onComplete()"))
.doOnError(e -> LOGGER.log(Level.SEVERE, "getAccountByAddress(" + address + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -91,6 +110,9 @@ public class XmppAccountRepository
return dao.getAll().observableResult()
.map(ResultDelegate::toList)
.map(this::modelsToEntities)
.doOnNext(l -> LOGGER.log(LEVEL, "observeAllAccounts(): onNext(): " + Arrays.toString(l.toArray())))
.doOnError(e -> LOGGER.log(Level.SEVERE, "observeAllAccounts(): onError()", e))
.doOnComplete(() -> LOGGER.log(LEVEL, "observeAllAccounts(): onComplete()"))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -100,6 +122,9 @@ public class XmppAccountRepository
return dao.getAll().observableResult()
.flatMap(ReactiveResult::observable)
.map(accountMapping::toEntity)
.doOnNext(a -> LOGGER.log(LEVEL, "observeAccounts(): onNext(): " + a))
.doOnError(e -> LOGGER.log(Level.SEVERE, "observeAccounts(): onError()", e))
.doOnComplete(() -> LOGGER.log(LEVEL, "observeAccounts(): onComplete()"))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -113,6 +138,8 @@ public class XmppAccountRepository
.map(model -> accountMapping.toModel(account, model))
.flatMap(updatedModel -> data().update(updatedModel))
.map(model -> accountMapping.toEntity(model, account))
.doOnSuccess(a -> LOGGER.log(LEVEL, "updateAccount(" + account + "): onSuccess(): " + a))
.doOnError(e -> LOGGER.log(Level.SEVERE, "updateAccount(" + account + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -125,6 +152,8 @@ public class XmppAccountRepository
.map(model -> accountMapping.toModel(account, model))
.flatMap(data()::update)
.map(model -> accountMapping.toEntity(model, account))
.doOnSuccess(a -> LOGGER.log(LEVEL, "upsertAccount(" + account + "): onSuccess(): " + a))
.doOnError(e -> LOGGER.log(Level.SEVERE, "upsertAccount(" + account + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}
@ -132,6 +161,8 @@ public class XmppAccountRepository
@Override
public Completable deleteAccount(UUID accountId) {
return dao.delete(accountId).ignoreElement()
.doOnComplete(() -> LOGGER.log(LEVEL, "deleteAccount(" + accountId + "): onComplete()"))
.doOnError(e -> LOGGER.log(Level.SEVERE, "deleteAccount(" + accountId + "): onError()", e))
.subscribeOn(subscriberScheduler())
.observeOn(observerScheduler());
}

View File

@ -6,13 +6,13 @@ dependencies {
// Smack
// Not all of those are needed, but it may be a good idea to define those versions explicitly
api "org.igniterealtime.smack:smack-core:$smackCoreVersion"
api "org.igniterealtime.smack:smack-experimental:$smackExperimentalVersion"
api "org.igniterealtime.smack:smack-extensions:$smackExtensionsVersion"
api "org.igniterealtime.smack:smack-im:$smackImVersion"
api "org.igniterealtime.smack:smack-tcp:$smackTcpVersion"
implementation 'org.igniterealtime.smack:smack-core:'
implementation 'org.igniterealtime.smack:smack-experimental:'
implementation 'org.igniterealtime.smack:smack-extensions:'
implementation 'org.igniterealtime.smack:smack-im:'
implementation 'org.igniterealtime.smack:smack-tcp:'
testImplementation "org.igniterealtime.smack:smack-java7:$smackJava7Version"
testImplementation 'org.igniterealtime.smack:smack-java7:'
// RxJava2
implementation "io.reactivex.rxjava2:rxjava:$rxJava2Version"
@ -21,8 +21,8 @@ dependencies {
implementation "com.google.dagger:dagger:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
compileOnly 'org.projectlombok:lombok:1.18.10'
annotationProcessor 'org.projectlombok:lombok:1.18.10'
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
// JUnit for testing
testImplementation "junit:junit:$junitVersion"

View File

@ -1,86 +1,51 @@
package org.mercury_im.messenger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.csi.ClientStateIndicationManager;
import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.jivesoftware.smackx.iqversion.VersionManager;
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;
import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
import org.mercury_im.messenger.data.repository.Repositories;
import org.mercury_im.messenger.usecase.AddAccount;
import org.mercury_im.messenger.usecase.RosterStoreBinder;
import org.mercury_im.messenger.xmpp.MercuryConnection;
import org.mercury_im.messenger.store.MercuryEntityCapsStore;
import org.mercury_im.messenger.xmpp.MercuryConnectionManager;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;
import javax.inject.Singleton;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
@Singleton
public class Messenger implements ClientStateListener {
public class Messenger {
public static final String TAG = "MercuryIM";
private static final Logger LOGGER = Logger.getLogger(Messenger.class.getName());
private final MercuryConnectionManager connectionManager;
private final Repositories repositories;
private CompositeDisposable disposable = new CompositeDisposable();
static {
ReconnectionManager.setEnabledPerDefault(true);
ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
VersionManager.setAutoAppendSmackVersion(false);
VersionManager.setDefaultVersion("Mercury-IM", "0.0.1-little-joe");
DeliveryReceiptManager.setDefaultAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.ifIsSubscribed);
StableUniqueStanzaIdManager.setEnabledByDefault(true);
}
@Inject
public Messenger(Repositories repositories, MercuryConnectionManager connectionManager) {
public Messenger(Repositories repositories,
MercuryConnectionManager connectionManager,
MercuryEntityCapsStore entityCapsStore) {
this.repositories = repositories;
this.connectionManager = connectionManager;
performInitialLogin();
connectionManager.setRepositories(repositories);
EntityCapsManager.setPersistentCache(entityCapsStore);
getConnectionManager().connectActiveAccounts();
}
public MercuryConnectionManager getConnectionManager() {
return connectionManager;
}
public void performInitialLogin() {
LOGGER.log(Level.INFO, "Perform initial login.");
disposable.add(repositories.getAccountRepository().observeAllAccounts().firstOrError()
.subscribeOn(Schedulers.newThread())
.subscribe(connectionManager::registerConnections));
}
public AddAccount addAccount() {
return new AddAccount(repositories.getAccountRepository(), this.connectionManager);
}
// CSI
@Override
public void onClientInForeground() {
LOGGER.log(Level.INFO, "CSI: active");
for (MercuryConnection connection : connectionManager.getConnections()) {
tryCsiActive(connection);
}
}
@Override
public void onClientInBackground() {
LOGGER.log(Level.INFO, "CSI: inactive");
for (MercuryConnection connection : connectionManager.getConnections()) {
tryCsiInactive(connection);
}
}
private void tryCsiActive(MercuryConnection connection) {
try {
ClientStateIndicationManager.active(connection.getConnection());
} catch (SmackException.NotConnectedException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Sending CSI state 'active' failed.", e);
}
}
private void tryCsiInactive(MercuryConnection connection) {
try {
ClientStateIndicationManager.inactive(connection.getConnection());
} catch (SmackException.NotConnectedException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Sending CSI state 'inactive' failed.", e);
}
}
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.usecase;
package org.mercury_im.messenger.store;
import org.jivesoftware.smack.roster.Roster;
import org.mercury_im.messenger.data.repository.AccountRepository;

View File

@ -1,82 +0,0 @@
package org.mercury_im.messenger.usecase;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.xmpp.MercuryConnection;
import org.mercury_im.messenger.xmpp.MercuryConnectionManager;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.Completable;
import io.reactivex.Single;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class AddAccount {
private static final Logger LOGGER = Logger.getLogger(AddAccount.class.getName());
private final AccountRepository accountRepository;
private final MercuryConnectionManager connectionManager;
private final CompositeDisposable disposable = new CompositeDisposable();
public AddAccount(AccountRepository accountRepository, MercuryConnectionManager connectionManager) {
this.accountRepository = accountRepository;
this.connectionManager = connectionManager;
}
public Completable execute(Account account) {
return loginAndStoreAccountIfSuccessful(account);
}
private Completable loginAndStoreAccountIfSuccessful(Account account) {
LOGGER.log(Level.INFO, "loginAndStoreIfSuccessful");
return logIntoAccount(account).flatMap(connection ->
insertEnabledAccountIntoDatabase(account).flatMap(insertedAccount ->
updateAccountIdInConnectionSingle(insertedAccount, connection)))
.map(this::addConnectionToMessenger)
.ignoreElement();
}
private Single<MercuryConnection> logIntoAccount(Account account) {
return getOrCreateConnectionSingle(account)
.doAfterSuccess(con -> LogIntoAccount.with(con).executeAndPossiblyThrow())
.subscribeOn(Schedulers.io());
}
private Single<MercuryConnection> getOrCreateConnectionSingle(Account account) {
return Single.fromCallable(() -> getOrCreateConnection(account));
}
private MercuryConnection getOrCreateConnection(Account account) {
MercuryConnection connection = connectionManager.getConnection(account);
if (connection == null) {
connection = new MercuryConnection(accountRepository, account);
}
return connection;
}
private Single<Account> insertEnabledAccountIntoDatabase(Account account) {
account.setEnabled(true);
return accountRepository.upsertAccount(account);
}
private Completable addConnectionToMessenger(MercuryConnection connection) {
return Completable.fromAction(() -> connectionManager.registerConnection(connection));
}
private Single<MercuryConnection> updateAccountIdInConnectionSingle(Account account, MercuryConnection connection) {
return Single.fromCallable(() -> {
updateAccountIdInConnection(account, connection);
return connection;
});
}
private void updateAccountIdInConnection(Account account, MercuryConnection connection) {
if (connection != null) {
connection.getAccount().setId(account.getId());
}
}
}

View File

@ -1,17 +0,0 @@
package org.mercury_im.messenger.usecase;
import io.reactivex.Completable;
public interface AddAccountUseCase {
AddAccountTask create();
Completable execute(AddAccountTask task);
interface AddAccountTask {
void setAddress(String address);
void setPassword(String password);
}
}

View File

@ -1,74 +0,0 @@
package org.mercury_im.messenger.usecase;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLErrorException;
import org.mercury_im.messenger.xmpp.MercuryConnection;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.Completable;
import io.reactivex.Single;
public class LogIntoAccount {
public enum ConnectionResult {
success,
credential_error,
server_error,
other_error
}
private static final Logger LOGGER = Logger.getLogger(LogIntoAccount.class.getName());
private final MercuryConnection connection;
private LogIntoAccount(MercuryConnection connection) {
this.connection = connection;
}
public static LogIntoAccount with(MercuryConnection connection) {
if (connection == null) {
throw new NullPointerException("MercuryConnection cannot be null.");
}
return new LogIntoAccount(connection);
}
public Completable executeAndPossiblyThrow() {
return Completable.fromAction(this::doAuthenticateIfNecessary);
}
public Single<ConnectionResult> execute() {
return Single.fromCallable(this::authenticateIfNecessary);
}
private ConnectionResult authenticateIfNecessary() {
try {
doAuthenticateIfNecessary();
return ConnectionResult.success;
} catch (SASLErrorException e) {
LOGGER.log(Level.WARNING, "SASL Error while connecting to account " + connection.getAccount().getAddress(), e);
return ConnectionResult.credential_error;
} catch (SmackException.ConnectionException e) {
LOGGER.log(Level.WARNING, "Connectivity error while connecting to account " + connection.getAccount().getAddress(), e);
return ConnectionResult.server_error;
}
catch (IOException | XMPPException | SmackException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Error connecting to account " + connection.getAccount().getAddress(), e);
return ConnectionResult.other_error;
}
}
private void doAuthenticateIfNecessary()
throws InterruptedException, XMPPException, SmackException, IOException {
if (!connection.getConnection().isAuthenticated()) {
LOGGER.log(Level.INFO, "Logging in");
((AbstractXMPPConnection) connection.getConnection()).connect().login();
LOGGER.log(Level.INFO, "Login complete");
}
}
}

View File

@ -0,0 +1,25 @@
package org.mercury_im.messenger.util;
import java.util.Iterator;
import java.util.Map;
import io.reactivex.functions.Function;
public class DebugUtils {
public static <K, V> String mapToString(Map<K, V> map) throws Exception {
return mapToString(map, K::toString, V::toString);
}
public static <K, V> String mapToString(Map<K, V> map, Function<K, String> keyToString, Function<V, String> valueToString) throws Exception {
StringBuilder sb = new StringBuilder("[");
for (Iterator<Map.Entry<K, V>> iterator = map.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<K, V> entry = iterator.next();
sb.append(keyToString.apply(entry.getKey())).append(": ").append(valueToString.apply(entry.getValue()));
if (iterator.hasNext()) {
sb.append(",\n");
}
}
return sb.append(']').toString();
}
}

View File

@ -24,4 +24,9 @@ public class Optional<T> {
public boolean isPresent() {
return item != null;
}
@Override
public String toString() {
return "Optional(" + (isPresent() ? getItem().toString() : "null") + ")";
}
}

View File

@ -1,25 +1,26 @@
package org.mercury_im.messenger.xmpp;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.util.Optional;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.subjects.BehaviorSubject;
public class MercuryConnection {
private static final Logger LOGGER = Logger.getLogger("MercuryConnection");
private static final XmppConnectionFactory connectionFactory = new XmppConnectionFactory();
private final CompositeDisposable disposable = new CompositeDisposable();
private final AccountRepository accountRepository;
private Account account;
private XMPPConnection connection;
@ -27,55 +28,30 @@ public class MercuryConnection {
private BehaviorSubject<Boolean> enabled = BehaviorSubject.create();
private BehaviorSubject<ConnectionState> state = BehaviorSubject.createDefault(ConnectionState.closed);
public MercuryConnection(AccountRepository accountRepository, Account account) {
this.accountRepository = accountRepository;
public MercuryConnection(Account account, XMPPConnection connection) {
this.account = account;
this.connection = connectionFactory.createConnection(account);
observeAccountAndConnection();
this.connection = connection;
}
public Observable<ConnectionState> getState() {
return state;
}
private void observeAccountAndConnection() {
observeAccount();
public void observeAccountAndConnection(AccountRepository accountRepository) {
observeAccount(accountRepository);
observeConnection();
}
private void observeAccount() {
disposable.add(accountRepository.observeAccount(account.getId())
private Disposable observeAccount(AccountRepository accountRepository) {
return accountRepository.observeAccount(account.getId())
.filter(Optional::isPresent)
.map(Optional::getItem)
.subscribe(this::setAccount));
.subscribe(this::setAccount);
}
private void observeConnection() {
connection.addConnectionListener(new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
LOGGER.log(Level.FINER, "connected");
state.onNext(ConnectionState.connected);
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
LOGGER.log(Level.FINER, "authenticated. resumed? " + resumed);
state.onNext(ConnectionState.authenticated);
}
@Override
public void connectionClosed() {
LOGGER.log(Level.FINER, "connectionClosed");
state.onNext(ConnectionState.closed);
}
@Override
public void connectionClosedOnError(Exception e) {
LOGGER.log(Level.WARNING, "connectionClosedOnError");
state.onNext(ConnectionState.closedOnError);
}
});
// TODO: Remove listener at some point
connection.addConnectionListener(connectionListener);
}
private void setAccount(Account account) {
@ -91,8 +67,39 @@ public class MercuryConnection {
return connection;
}
public void dispose() {
disposable.dispose();
private final ConnectionListener connectionListener = new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
LOGGER.log(Level.FINER, "connected");
state.onNext(ConnectionState.connected);
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
LOGGER.log(Level.FINER, "authenticated. resumed? " + resumed);
state.onNext(ConnectionState.authenticated);
}
@Override
public void connectionClosed() {
LOGGER.log(Level.FINER, "connectionClosed");
state.onNext(ConnectionState.closed);
}
@Override
public void connectionClosedOnError(Exception e) {
LOGGER.log(Level.WARNING, "connectionClosedOnError");
state.onNext(ConnectionState.closedOnError);
}
};
@Override
public String toString() {
return "MercuryConnection(" + getAccount() + ")";
}
public void login() throws InterruptedException, XMPPException, SmackException, IOException {
((AbstractXMPPConnection) connection).connect().login();
}
public enum ConnectionState {

View File

@ -3,19 +3,17 @@ package org.mercury_im.messenger.xmpp;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ReconnectionListener;
import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smack.sm.packet.StreamManagement;
import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.jivesoftware.smackx.iqversion.VersionManager;
import org.jivesoftware.smackx.receipts.DeliveryReceiptManager;
import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLErrorException;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.csi.ClientStateIndicationManager;
import org.mercury_im.messenger.ClientStateListener;
import org.mercury_im.messenger.data.repository.Repositories;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.store.MercuryEntityCapsStore;
import org.mercury_im.messenger.usecase.LogIntoAccount;
import org.mercury_im.messenger.usecase.RosterStoreBinder;
import org.mercury_im.messenger.util.Optional;
import org.mercury_im.messenger.store.RosterStoreBinder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -29,85 +27,38 @@ import javax.inject.Singleton;
import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject;
@Singleton
public class MercuryConnectionManager {
public class MercuryConnectionManager implements ClientStateListener {
private static final Logger LOGGER = Logger.getLogger("ConnectionManager");
private static final XmppConnectionFactory connectionFactory = new XmppConnectionFactory();
private final Map<UUID, MercuryConnection> connections = new ConcurrentHashMap<>();
private final BehaviorSubject<Map<UUID, MercuryConnection>> connectionsSubject = BehaviorSubject.createDefault(connections);
private final AccountRepository accountRepository;
private final RosterStoreBinder rosterStoreBinder;
private final MercuryEntityCapsStore entityCapsStore;
private final CompositeDisposable disposable = new CompositeDisposable();
static {
ReconnectionManager.setEnabledPerDefault(true);
ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
VersionManager.setAutoAppendSmackVersion(false);
VersionManager.setDefaultVersion("Mercury-IM", "0.0.1-little-joe");
DeliveryReceiptManager.setDefaultAutoReceiptMode(DeliveryReceiptManager.AutoReceiptMode.ifIsSubscribed);
StableUniqueStanzaIdManager.setEnabledByDefault(true);
}
private Repositories repositories;
private CompositeDisposable disposable = new CompositeDisposable();
@Inject
public MercuryConnectionManager(Repositories repositories,
RosterStoreBinder rosterStoreBinder,
MercuryEntityCapsStore entityCapsStore) {
this.accountRepository = repositories.getAccountRepository();
public MercuryConnectionManager(RosterStoreBinder rosterStoreBinder) {
this.rosterStoreBinder = rosterStoreBinder;
this.entityCapsStore = entityCapsStore;
EntityCapsManager.setPersistentCache(entityCapsStore);
}
public List<MercuryConnection> getConnections() {
return new ArrayList<>(connections.values());
}
public Observable<Map<UUID, MercuryConnection>> observeConnections() {
return connectionsSubject;
}
public MercuryConnection getConnection(Account account) {
return getConnection(account.getId());
}
public MercuryConnection getConnection(UUID id) {
return connections.get(id);
}
public void registerConnections(List<Account> accounts) {
for (Account account : accounts) {
MercuryConnection connection = new MercuryConnection(accountRepository, account);
registerConnection(connection);
public MercuryConnection getOrCreateConnection(Account account) {
MercuryConnection connection = connections.get(account.getId());
if (connection == null) {
connection = new MercuryConnection(account, connectionFactory.createConnection(account));
bindConnection(connection);
connections.put(account.getId(), connection);
}
}
public void registerConnection(MercuryConnection connection) {
LOGGER.log(Level.INFO, "Register Connection " + connection.getAccount().getAddress());
putConnection(connection);
disposable.add(accountRepository
.observeAccount(connection.getAccount().getId())
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.newThread())
.subscribe(event ->
handleOptionalAccountChangedEvent(connection, event)));
}
private void putConnection(MercuryConnection connection) {
connections.put(connection.getAccount().getId(), connection);
connectionsSubject.onNext(connections);
bindConnection(connection);
return connection;
}
public void bindConnection(MercuryConnection connection) {
@ -126,57 +77,70 @@ public class MercuryConnectionManager {
});
}
private void handleOptionalAccountChangedEvent(MercuryConnection connection, Optional<Account> event) {
if (event.isPresent()) {
handleAccountChangedEvent(connection, event.getItem());
} else {
handleAccountRemoved(connection);
public void connectActiveAccounts() {
Disposable d = repositories.getAccountRepository()
.observeAllAccounts()
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.newThread())
.firstOrError()
.flatMapObservable(Observable::fromIterable)
.doOnNext(account -> Async.go(() -> {
MercuryConnection connection = getOrCreateConnection(account);
if (connection.getAccount().isEnabled()) {
try {
connection.login();
} catch (SASLErrorException e) {
LOGGER.log(Level.SEVERE, "Account Credentials incorrect", e);
((AbstractXMPPConnection) connection.getConnection()).disconnect();
ReconnectionManager.getInstanceFor((AbstractXMPPConnection) connection.getConnection()).disableAutomaticReconnection();
} catch (IOException | InterruptedException | SmackException | XMPPException e) {
e.printStackTrace();
}
}
}))
.subscribe();
disposable.add(d);
}
// CSI
@Override
public void onClientInForeground() {
LOGGER.log(Level.INFO, "CSI: active");
for (MercuryConnection connection : getConnections()) {
tryCsiActive(connection);
}
}
private void handleAccountChangedEvent(MercuryConnection connection, Account account) {
if (account.isEnabled()) {
handleAccountEnabled(connection);
} else {
handleAccountDisabled(connection);
@Override
public void onClientInBackground() {
LOGGER.log(Level.INFO, "CSI: inactive");
for (MercuryConnection connection : getConnections()) {
tryCsiInactive(connection);
}
}
private void handleAccountDisabled(MercuryConnection connection) {
LOGGER.log(Level.FINER, "HandleAccountDisabled: " + connection.getAccount().getAddress());
connectionDisconnect(connection);
private void tryCsiActive(MercuryConnection connection) {
try {
ClientStateIndicationManager.active(connection.getConnection());
} catch (SmackException.NotConnectedException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Sending CSI state 'active' failed.", e);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "CSI not supported by server.");
}
}
private void handleAccountEnabled(MercuryConnection connection) {
LOGGER.log(Level.FINER, "HandleAccountEnabled: " + connection.getAccount().getAddress());
connectionLogin(connection);
private void tryCsiInactive(MercuryConnection connection) {
try {
ClientStateIndicationManager.inactive(connection.getConnection());
} catch (SmackException.NotConnectedException | InterruptedException e) {
LOGGER.log(Level.WARNING, "Sending CSI state 'inactive' failed.", e);
} catch (IllegalArgumentException e) {
LOGGER.log(Level.WARNING, "CSI not supported by server.");
}
}
private void connectionLogin(MercuryConnection connection) {
disposable.add(LogIntoAccount.with(connection).executeAndPossiblyThrow()
.subscribeOn(Schedulers.newThread())
.subscribe(() -> LOGGER.log(Level.FINER, "Logged in."),
error -> LOGGER.log(Level.SEVERE, "Connection error!", error)));
public void setRepositories(Repositories repositories) {
this.repositories = repositories;
}
private void handleAccountRemoved(MercuryConnection connection) {
disconnectAndRemoveConnection(connection);
}
private void disconnectAndRemoveConnection(MercuryConnection connection) {
connectionDisconnect(connection);
removeConnection(connection);
}
private void connectionDisconnect(MercuryConnection connection) {
((AbstractXMPPConnection) connection.getConnection()).disconnect();
}
private void removeConnection(MercuryConnection connection) {
LOGGER.log(Level.FINER, "Remove Connection: " + connection.getAccount().getAddress());
connections.remove(connection.getAccount().getId());
connectionsSubject.onNext(connections);
connection.dispose();
}
}

View File

@ -53,7 +53,8 @@ public class XmppDirectMessageCenter
this.directChatRepository = repositories.getDirectChatRepository();
this.messageRepository = repositories.getMessageRepository();
XMPPConnection connection = getMessenger().getConnectionManager().getConnection(account).getConnection();
XMPPConnection connection = getMessenger().getConnectionManager()
.getOrCreateConnection(account).getConnection();
ChatManager.getInstanceFor(connection).addIncomingListener(this);
}
@ -98,7 +99,8 @@ public class XmppDirectMessageCenter
}
protected ChatManager getChatManager(DirectChat chat) {
MercuryConnection mercuryConnection = getMessenger().getConnectionManager().getConnection(chat.getAccount());
MercuryConnection mercuryConnection = getMessenger().getConnectionManager()
.getOrCreateConnection(chat.getAccount());
return ChatManager.getInstanceFor(mercuryConnection.getConnection());
}

View File

@ -1,7 +1,6 @@
package org.mercury_im.messenger.learning_tests.smack;
import org.junit.Test;
import org.mercury_im.messenger.usecase.AddAccountUseCase;
import java.util.UUID;
@ -9,8 +8,10 @@ public class AddAccountUseCaseTest {
@Test
public void test() {
/*
AddAccountUseCase useCase;
AddAccountUseCase.AddAccountTask task;
*/
System.out.println(UUID.randomUUID());
}

View File

@ -0,0 +1,68 @@
package org.mercury_im.messenger.repository;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.util.Optional;
import java.util.List;
import java.util.UUID;
import io.reactivex.Completable;
import io.reactivex.Maybe;
import io.reactivex.Observable;
import io.reactivex.Single;
public class TestAccountRepository implements AccountRepository {
@Override
public Single<Account> insertAccount(Account account) {
return null;
}
@Override
public Observable<Optional<Account>> observeAccount(UUID accountId) {
return null;
}
@Override
public Maybe<Account> getAccount(UUID accountId) {
return null;
}
@Override
public Observable<Optional<Account>> observeAccountByAddress(String address) {
return null;
}
@Override
public Maybe<Account> getAccountByAddress(String address) {
return null;
}
@Override
public Observable<List<Account>> observeAllAccounts() {
return null;
}
@Override
public Observable<Account> observeAccounts() {
return null;
}
@Override
public Single<Account> updateAccount(Account account) {
return null;
}
@Override
public Single<Account> upsertAccount(Account account) {
return null;
}
@Override
public Completable deleteAccount(UUID accountId) {
return null;
}
}

View File

@ -0,0 +1,145 @@
package org.mercury_im.messenger.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject;
public class ObservableList<T> implements List<T> {
private List<T> items = new ArrayList<>();
private BehaviorSubject<List<T>> listObservable = BehaviorSubject.createDefault(items);
private BehaviorSubject<Optional<T>> itemObservable = BehaviorSubject.create();
public ObservableList() {
}
@Override
public boolean add(T t) {
itemObservable.onNext(new Optional<>(t));
items.add(t);
listObservable.onNext(items);
return true;
}
@Override
public boolean remove(Object o) {
boolean remove = items.remove(o);
if (remove) {
itemObservable.onNext(new Optional<>());
listObservable.onNext(items);
}
return remove;
}
@Override
public int size() {
return items.size();
}
@Override
public boolean isEmpty() {
return items.isEmpty();
}
@Override
public boolean contains(Object o) {
return items.contains(o);
}
@Override
public Iterator<T> iterator() {
return items.iterator();
}
@Override
public Object[] toArray() {
return items.toArray();
}
@Override
public <T1> T1[] toArray(T1[] t1s) {
return items.toArray(t1s);
}
@Override
public boolean containsAll(Collection<?> collection) {
return items.containsAll(collection);
}
@Override
public boolean addAll(Collection<? extends T> collection) {
return items.addAll(collection);
}
@Override
public boolean addAll(int i, Collection<? extends T> collection) {
return items.addAll(i, collection);
}
@Override
public boolean removeAll(Collection<?> collection) {
return items.removeAll(collection);
}
@Override
public boolean retainAll(Collection<?> collection) {
return items.retainAll(collection);
}
@Override
public void clear() {
items.clear();
}
@Override
public T get(int i) {
return items.get(i);
}
@Override
public T set(int i, T t) {
return items.set(i, t);
}
@Override
public void add(int i, T t) {
items.add(i, t);
}
@Override
public T remove(int i) {
return items.remove(i);
}
@Override
public int indexOf(Object o) {
return items.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return items.lastIndexOf(o);
}
@Override
public ListIterator<T> listIterator() {
return items.listIterator();
}
@Override
public ListIterator<T> listIterator(int i) {
return items.listIterator(i);
}
@Override
public List<T> subList(int i, int i1) {
return items.subList(i, i1);
}
}

View File

@ -0,0 +1,10 @@
package org.mercury_im.messenger.xmpp;
import org.mercury_im.messenger.xmpp.MercuryConnectionManager;
public class MercuryConnectionManagerTest {
public void test() {
MercuryConnectionManager manager = new MercuryConnectionManager(null);
}
}

View File

@ -82,4 +82,9 @@ public class IAccount implements Account {
public boolean isEnabled() {
return enabled;
}
@Override
public String toString() {
return "Account(" + getId().toString() + " " + getAddress() + ")";
}
}

View File

@ -1,6 +1,6 @@
#Sun Sep 01 01:05:38 CEST 2019
#Wed Apr 22 19:21:25 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4-rc-1-all.zip

@ -1 +1 @@
Subproject commit a71ce2ca36faab3bd026dc492b0b8ab8266440d9
Subproject commit e79710840be6d6b3301e078a23688eafaa06013c

4
raw/Account Normal file
View File

@ -0,0 +1,4 @@
enable
disable

4
raw/Conversation Normal file
View File

@ -0,0 +1,4 @@
send(Message)
getMessages

10
raw/Messenger Normal file
View File

@ -0,0 +1,10 @@
start
setupFeatures
connectAllAccounts
getConversation(Account, User/Room)
addAccount(Account)
removeAccount(Account)

View File

@ -2,6 +2,5 @@ include ':entity',
':data',
':domain',
':app'
// ':core-old'
includeBuild 'libs/Smack'
includeBuild('libs/Smack/')

View File

@ -7,7 +7,8 @@ ext {
// Version Strings for non-unique releases
//*
smackVersion = shortVersion
//smackVersion = shortVersion
smackVersion = "4.4.0-alpha3-SNAPSHOT"
smackAndroidVersion = smackVersion
smackAndroidExtensionsVersion = smackVersion
@ -73,7 +74,7 @@ ext {
// Other libraries
// Architecture Components
lifecycleVersion = '2.2.0-rc03'
lifecycleVersion = '2.3.0-alpha01'
pagingVersion = "2.1.0"
appCompatVersion = '1.1.0'
@ -86,7 +87,7 @@ ext {
rxAndroidVersion = "2.1.1"
// Dagger 2
daggerVersion = '2.25.4'
daggerVersion = '2.27'
// Android Support Library
supportLibVersion = "28.0.0"
@ -103,6 +104,8 @@ ext {
andxTestCoreVersion = "1.2.0"
andxTestEspressoVersion = "3.2.0"
lombokVersion = '1.18.12'
// Requery
requeryVersion = "1.6.1"
}