diff --git a/.editorconfig b/.editorconfig index 1966f917635..60d4fd6cae9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,14 +1,901 @@ -# For ktlint configuration. Ref: https://ktlint.github.io/ - -[*.{kt,kts}] -# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely) -indent_size=unset -# true (recommended) / false -insert_final_newline=true -# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off" -# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide) -max_line_length=off - -# From https://github.com/pinterest/ktlint#custom-ktlint-specific-editorconfig-properties -# default IntelliJ IDEA style, same as alphabetical, but with "java", "javax", "kotlin" and alias imports in the end of the imports list -ij_kotlin_imports_layout=*,java.**,javax.**,kotlin.**,^ +[*] +charset = utf-8 +end_of_line = crlf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 160 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = false +ij_smart_tabs = false +ij_visual_guides = none +ij_wrap_on_typing = false + +[*.java] +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = false +ij_java_align_multiline_array_initializer_expression = false +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = false +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = false +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = false +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = false +ij_java_array_initializer_right_brace_on_new_line = false +ij_java_array_initializer_wrap = off +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_at_first_column = true +ij_java_builder_methods = none +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = off +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 99 +ij_java_class_names_in_javadoc = 1 +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = false +ij_java_do_while_brace_force = never +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_enum_constants_wrap = off +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = off +ij_java_field_annotation_wrap = split_into_lines +ij_java_finally_on_new_line = false +ij_java_for_brace_force = never +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = false +ij_java_generate_final_parameters = false +ij_java_if_brace_force = never +ij_java_imports_layout = $android.**,$androidx.**,$com.**,$junit.**,$net.**,$org.**,$java.**,$javax.**,$*,|,android.**,|,androidx.**,|,com.**,|,junit.**,|,net.**,|,org.**,|,java.**,|,javax.**,|,*,| +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_builder_methods_indents = false +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_at_first_column = true +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = off +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = off +ij_java_modifier_list_wrap = false +ij_java_names_count_to_use_import_on_demand = 99 +ij_java_new_line_after_lparen_in_record_header = false +ij_java_parameter_annotation_wrap = off +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_record_header = false +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_record_header = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = off +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = off +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = off +ij_java_visibility = public +ij_java_while_brace_force = never +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false + +[*.properties] +ij_properties_align_group_field_declarations = false +ij_properties_keep_blank_lines = false +ij_properties_key_value_delimiter = equals +ij_properties_spaces_around_key_value_delimiter = false + +[.editorconfig] +ij_editorconfig_align_group_field_declarations = false +ij_editorconfig_space_after_colon = false +ij_editorconfig_space_after_comma = true +ij_editorconfig_space_before_colon = false +ij_editorconfig_space_before_comma = false +ij_editorconfig_spaces_around_assignment_operators = true + +[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.rng,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}] +ij_continuation_indent_size = 4 +ij_xml_align_attributes = false +ij_xml_align_text = false +ij_xml_attribute_wrap = normal +ij_xml_block_comment_at_first_column = true +ij_xml_keep_blank_lines = 2 +ij_xml_keep_indents_on_empty_lines = false +ij_xml_keep_line_breaks = false +ij_xml_keep_line_breaks_in_text = true +ij_xml_keep_whitespaces = false +ij_xml_keep_whitespaces_around_cdata = preserve +ij_xml_keep_whitespaces_inside_cdata = false +ij_xml_line_comment_at_first_column = true +ij_xml_space_after_tag_name = false +ij_xml_space_around_equals_in_attribute = false +ij_xml_space_inside_empty_tag = true +ij_xml_text_wrap = normal +ij_xml_use_custom_settings = true + +[{*.bash,*.sh,*.zsh}] +indent_size = 2 +tab_width = 2 +ij_shell_binary_ops_start_line = false +ij_shell_keep_column_alignment_padding = false +ij_shell_minify_program = false +ij_shell_redirect_followed_by_space = false +ij_shell_switch_cases_indented = false +ij_shell_use_unix_line_separator = true + +[{*.c,*.c++,*.cc,*.cp,*.cpp,*.cu,*.cuh,*.cxx,*.h,*.h++,*.hh,*.hp,*.hpp,*.hxx,*.i,*.icc,*.ii,*.inl,*.ino,*.ipp,*.m,*.mm,*.pch,*.tcc,*.tpp}] +ij_c_add_brief_tag = false +ij_c_add_getter_prefix = true +ij_c_add_setter_prefix = true +ij_c_align_dictionary_pair_values = false +ij_c_align_group_field_declarations = false +ij_c_align_init_list_in_columns = true +ij_c_align_multiline_array_initializer_expression = true +ij_c_align_multiline_assignment = true +ij_c_align_multiline_binary_operation = true +ij_c_align_multiline_chained_methods = false +ij_c_align_multiline_for = true +ij_c_align_multiline_ternary_operation = true +ij_c_array_initializer_comma_on_next_line = false +ij_c_array_initializer_new_line_after_left_brace = false +ij_c_array_initializer_right_brace_on_new_line = false +ij_c_array_initializer_wrap = normal +ij_c_assignment_wrap = off +ij_c_binary_operation_sign_on_next_line = false +ij_c_binary_operation_wrap = normal +ij_c_blank_lines_after_class_header = 0 +ij_c_blank_lines_after_imports = 1 +ij_c_blank_lines_around_class = 1 +ij_c_blank_lines_around_field = 0 +ij_c_blank_lines_around_field_in_interface = 0 +ij_c_blank_lines_around_method = 1 +ij_c_blank_lines_around_method_in_interface = 1 +ij_c_blank_lines_around_namespace = 0 +ij_c_blank_lines_around_properties_in_declaration = 0 +ij_c_blank_lines_around_properties_in_interface = 0 +ij_c_blank_lines_before_imports = 1 +ij_c_blank_lines_before_method_body = 0 +ij_c_block_brace_placement = end_of_line +ij_c_block_brace_style = end_of_line +ij_c_block_comment_at_first_column = true +ij_c_catch_on_new_line = false +ij_c_class_brace_style = end_of_line +ij_c_class_constructor_init_list_align_multiline = true +ij_c_class_constructor_init_list_comma_on_next_line = false +ij_c_class_constructor_init_list_new_line_after_colon = never +ij_c_class_constructor_init_list_new_line_before_colon = if_long +ij_c_class_constructor_init_list_wrap = normal +ij_c_copy_is_deep = false +ij_c_create_interface_for_categories = true +ij_c_declare_generated_methods = true +ij_c_description_include_member_names = true +ij_c_discharged_short_ternary_operator = false +ij_c_do_not_add_breaks = false +ij_c_do_while_brace_force = never +ij_c_else_on_new_line = false +ij_c_enum_constants_comma_on_next_line = false +ij_c_enum_constants_wrap = on_every_item +ij_c_for_brace_force = never +ij_c_for_statement_new_line_after_left_paren = false +ij_c_for_statement_right_paren_on_new_line = false +ij_c_for_statement_wrap = off +ij_c_function_brace_placement = end_of_line +ij_c_function_call_arguments_align_multiline = true +ij_c_function_call_arguments_align_multiline_pars = false +ij_c_function_call_arguments_comma_on_next_line = false +ij_c_function_call_arguments_new_line_after_lpar = false +ij_c_function_call_arguments_new_line_before_rpar = false +ij_c_function_call_arguments_wrap = normal +ij_c_function_non_top_after_return_type_wrap = normal +ij_c_function_parameters_align_multiline = true +ij_c_function_parameters_align_multiline_pars = false +ij_c_function_parameters_comma_on_next_line = false +ij_c_function_parameters_new_line_after_lpar = false +ij_c_function_parameters_new_line_before_rpar = false +ij_c_function_parameters_wrap = normal +ij_c_function_top_after_return_type_wrap = normal +ij_c_generate_additional_eq_operators = true +ij_c_generate_additional_rel_operators = true +ij_c_generate_class_constructor = true +ij_c_generate_comparison_operators_use_std_tie = false +ij_c_generate_instance_variables_for_properties = ask +ij_c_generate_operators_as_members = true +ij_c_header_guard_style_pattern = ${PROJECT_NAME}_${FILE_NAME}_${EXT} +ij_c_if_brace_force = never +ij_c_in_line_short_ternary_operator = true +ij_c_indent_block_comment = true +ij_c_indent_c_struct_members = 4 +ij_c_indent_case_from_switch = true +ij_c_indent_class_members = 4 +ij_c_indent_directive_as_code = false +ij_c_indent_implementation_members = 0 +ij_c_indent_inside_code_block = 4 +ij_c_indent_interface_members = 0 +ij_c_indent_interface_members_except_ivars_block = false +ij_c_indent_namespace_members = 4 +ij_c_indent_preprocessor_directive = 0 +ij_c_indent_visibility_keywords = 0 +ij_c_insert_override = true +ij_c_insert_virtual_with_override = false +ij_c_introduce_auto_vars = false +ij_c_introduce_const_params = false +ij_c_introduce_const_vars = false +ij_c_introduce_generate_property = false +ij_c_introduce_generate_synthesize = true +ij_c_introduce_globals_to_header = true +ij_c_introduce_prop_to_private_category = false +ij_c_introduce_static_consts = true +ij_c_introduce_use_ns_types = false +ij_c_ivars_prefix = _ +ij_c_keep_blank_lines_before_end = 2 +ij_c_keep_blank_lines_before_right_brace = 2 +ij_c_keep_blank_lines_in_code = 2 +ij_c_keep_blank_lines_in_declarations = 2 +ij_c_keep_case_expressions_in_one_line = false +ij_c_keep_control_statement_in_one_line = true +ij_c_keep_directive_at_first_column = true +ij_c_keep_first_column_comment = true +ij_c_keep_line_breaks = true +ij_c_keep_nested_namespaces_in_one_line = false +ij_c_keep_simple_blocks_in_one_line = true +ij_c_keep_simple_methods_in_one_line = true +ij_c_keep_structures_in_one_line = false +ij_c_lambda_capture_list_align_multiline = false +ij_c_lambda_capture_list_align_multiline_bracket = false +ij_c_lambda_capture_list_comma_on_next_line = false +ij_c_lambda_capture_list_new_line_after_lbracket = false +ij_c_lambda_capture_list_new_line_before_rbracket = false +ij_c_lambda_capture_list_wrap = off +ij_c_line_comment_add_space = false +ij_c_line_comment_at_first_column = true +ij_c_method_brace_placement = end_of_line +ij_c_method_call_arguments_align_by_colons = true +ij_c_method_call_arguments_align_multiline = false +ij_c_method_call_arguments_special_dictionary_pairs_treatment = true +ij_c_method_call_arguments_wrap = off +ij_c_method_call_chain_wrap = off +ij_c_method_parameters_align_by_colons = true +ij_c_method_parameters_align_multiline = false +ij_c_method_parameters_wrap = off +ij_c_namespace_brace_placement = end_of_line +ij_c_parentheses_expression_new_line_after_left_paren = false +ij_c_parentheses_expression_right_paren_on_new_line = false +ij_c_place_assignment_sign_on_next_line = false +ij_c_property_nonatomic = true +ij_c_put_ivars_to_implementation = true +ij_c_refactor_compatibility_aliases_and_classes = true +ij_c_refactor_properties_and_ivars = true +ij_c_release_style = ivar +ij_c_retain_object_parameters_in_constructor = true +ij_c_semicolon_after_method_signature = false +ij_c_shift_operation_align_multiline = true +ij_c_shift_operation_wrap = normal +ij_c_show_non_virtual_functions = false +ij_c_space_after_colon = true +ij_c_space_after_colon_in_selector = false +ij_c_space_after_comma = true +ij_c_space_after_cup_in_blocks = false +ij_c_space_after_dictionary_literal_colon = true +ij_c_space_after_for_semicolon = true +ij_c_space_after_init_list_colon = true +ij_c_space_after_method_parameter_type_parentheses = false +ij_c_space_after_method_return_type_parentheses = false +ij_c_space_after_pointer_in_declaration = false +ij_c_space_after_quest = true +ij_c_space_after_reference_in_declaration = false +ij_c_space_after_reference_in_rvalue = false +ij_c_space_after_structures_rbrace = true +ij_c_space_after_superclass_colon = true +ij_c_space_after_type_cast = true +ij_c_space_after_visibility_sign_in_method_declaration = true +ij_c_space_before_autorelease_pool_lbrace = true +ij_c_space_before_catch_keyword = true +ij_c_space_before_catch_left_brace = true +ij_c_space_before_catch_parentheses = true +ij_c_space_before_category_parentheses = true +ij_c_space_before_chained_send_message = true +ij_c_space_before_class_left_brace = true +ij_c_space_before_colon = true +ij_c_space_before_comma = false +ij_c_space_before_dictionary_literal_colon = false +ij_c_space_before_do_left_brace = true +ij_c_space_before_else_keyword = true +ij_c_space_before_else_left_brace = true +ij_c_space_before_for_left_brace = true +ij_c_space_before_for_parentheses = true +ij_c_space_before_for_semicolon = false +ij_c_space_before_if_left_brace = true +ij_c_space_before_if_parentheses = true +ij_c_space_before_init_list = false +ij_c_space_before_init_list_colon = true +ij_c_space_before_method_call_parentheses = false +ij_c_space_before_method_left_brace = true +ij_c_space_before_method_parentheses = false +ij_c_space_before_namespace_lbrace = true +ij_c_space_before_pointer_in_declaration = true +ij_c_space_before_property_attributes_parentheses = false +ij_c_space_before_protocols_brackets = true +ij_c_space_before_quest = true +ij_c_space_before_reference_in_declaration = true +ij_c_space_before_superclass_colon = true +ij_c_space_before_switch_left_brace = true +ij_c_space_before_switch_parentheses = true +ij_c_space_before_template_call_lt = false +ij_c_space_before_template_declaration_lt = false +ij_c_space_before_try_left_brace = true +ij_c_space_before_while_keyword = true +ij_c_space_before_while_left_brace = true +ij_c_space_before_while_parentheses = true +ij_c_space_between_adjacent_brackets = false +ij_c_space_between_operator_and_punctuator = false +ij_c_space_within_empty_array_initializer_braces = false +ij_c_spaces_around_additive_operators = true +ij_c_spaces_around_assignment_operators = true +ij_c_spaces_around_bitwise_operators = true +ij_c_spaces_around_equality_operators = true +ij_c_spaces_around_lambda_arrow = true +ij_c_spaces_around_logical_operators = true +ij_c_spaces_around_multiplicative_operators = true +ij_c_spaces_around_pm_operators = false +ij_c_spaces_around_relational_operators = true +ij_c_spaces_around_shift_operators = true +ij_c_spaces_around_unary_operator = false +ij_c_spaces_within_array_initializer_braces = false +ij_c_spaces_within_braces = true +ij_c_spaces_within_brackets = false +ij_c_spaces_within_cast_parentheses = false +ij_c_spaces_within_catch_parentheses = false +ij_c_spaces_within_category_parentheses = false +ij_c_spaces_within_empty_braces = false +ij_c_spaces_within_empty_function_call_parentheses = false +ij_c_spaces_within_empty_function_declaration_parentheses = false +ij_c_spaces_within_empty_lambda_capture_list_bracket = false +ij_c_spaces_within_empty_template_call_ltgt = false +ij_c_spaces_within_empty_template_declaration_ltgt = false +ij_c_spaces_within_for_parentheses = false +ij_c_spaces_within_function_call_parentheses = false +ij_c_spaces_within_function_declaration_parentheses = false +ij_c_spaces_within_if_parentheses = false +ij_c_spaces_within_lambda_capture_list_bracket = false +ij_c_spaces_within_method_parameter_type_parentheses = false +ij_c_spaces_within_method_return_type_parentheses = false +ij_c_spaces_within_parentheses = false +ij_c_spaces_within_property_attributes_parentheses = false +ij_c_spaces_within_protocols_brackets = false +ij_c_spaces_within_send_message_brackets = false +ij_c_spaces_within_switch_parentheses = false +ij_c_spaces_within_template_call_ltgt = false +ij_c_spaces_within_template_declaration_ltgt = false +ij_c_spaces_within_template_double_gt = true +ij_c_spaces_within_while_parentheses = false +ij_c_special_else_if_treatment = true +ij_c_superclass_list_after_colon = never +ij_c_superclass_list_align_multiline = true +ij_c_superclass_list_before_colon = if_long +ij_c_superclass_list_comma_on_next_line = false +ij_c_superclass_list_wrap = on_every_item +ij_c_tag_prefix_of_block_comment = at +ij_c_tag_prefix_of_line_comment = back_slash +ij_c_template_call_arguments_align_multiline = false +ij_c_template_call_arguments_align_multiline_pars = false +ij_c_template_call_arguments_comma_on_next_line = false +ij_c_template_call_arguments_new_line_after_lt = false +ij_c_template_call_arguments_new_line_before_gt = false +ij_c_template_call_arguments_wrap = off +ij_c_template_declaration_function_body_indent = false +ij_c_template_declaration_function_wrap = split_into_lines +ij_c_template_declaration_struct_body_indent = false +ij_c_template_declaration_struct_wrap = split_into_lines +ij_c_template_parameters_align_multiline = false +ij_c_template_parameters_align_multiline_pars = false +ij_c_template_parameters_comma_on_next_line = false +ij_c_template_parameters_new_line_after_lt = false +ij_c_template_parameters_new_line_before_gt = false +ij_c_template_parameters_wrap = off +ij_c_ternary_operation_signs_on_next_line = true +ij_c_ternary_operation_wrap = normal +ij_c_type_qualifiers_placement = before +ij_c_use_modern_casts = true +ij_c_use_setters_in_constructor = true +ij_c_while_brace_force = never +ij_c_while_on_new_line = false +ij_c_wrap_property_declaration = off + +[{*.cmake,CMakeLists.txt}] +ij_cmake_align_multiline_parameters_in_calls = false +ij_cmake_force_commands_case = 2 +ij_cmake_keep_blank_lines_in_code = 2 +ij_cmake_space_before_for_parentheses = true +ij_cmake_space_before_if_parentheses = true +ij_cmake_space_before_method_call_parentheses = false +ij_cmake_space_before_method_parentheses = false +ij_cmake_space_before_while_parentheses = true +ij_cmake_spaces_within_for_parentheses = false +ij_cmake_spaces_within_if_parentheses = false +ij_cmake_spaces_within_method_call_parentheses = false +ij_cmake_spaces_within_method_parentheses = false +ij_cmake_spaces_within_while_parentheses = false + +[{*.gant,*.gradle,*.groovy,*.gy}] +ij_groovy_align_group_field_declarations = false +ij_groovy_align_multiline_array_initializer_expression = false +ij_groovy_align_multiline_assignment = false +ij_groovy_align_multiline_binary_operation = false +ij_groovy_align_multiline_chained_methods = false +ij_groovy_align_multiline_extends_list = false +ij_groovy_align_multiline_for = true +ij_groovy_align_multiline_list_or_map = true +ij_groovy_align_multiline_method_parentheses = false +ij_groovy_align_multiline_parameters = true +ij_groovy_align_multiline_parameters_in_calls = false +ij_groovy_align_multiline_resources = true +ij_groovy_align_multiline_ternary_operation = false +ij_groovy_align_multiline_throws_list = false +ij_groovy_align_named_args_in_map = true +ij_groovy_align_throws_keyword = false +ij_groovy_array_initializer_new_line_after_left_brace = false +ij_groovy_array_initializer_right_brace_on_new_line = false +ij_groovy_array_initializer_wrap = off +ij_groovy_assert_statement_wrap = off +ij_groovy_assignment_wrap = off +ij_groovy_binary_operation_wrap = off +ij_groovy_blank_lines_after_class_header = 0 +ij_groovy_blank_lines_after_imports = 1 +ij_groovy_blank_lines_after_package = 1 +ij_groovy_blank_lines_around_class = 1 +ij_groovy_blank_lines_around_field = 0 +ij_groovy_blank_lines_around_field_in_interface = 0 +ij_groovy_blank_lines_around_method = 1 +ij_groovy_blank_lines_around_method_in_interface = 1 +ij_groovy_blank_lines_before_imports = 1 +ij_groovy_blank_lines_before_method_body = 0 +ij_groovy_blank_lines_before_package = 0 +ij_groovy_block_brace_style = end_of_line +ij_groovy_block_comment_at_first_column = true +ij_groovy_call_parameters_new_line_after_left_paren = false +ij_groovy_call_parameters_right_paren_on_new_line = false +ij_groovy_call_parameters_wrap = off +ij_groovy_catch_on_new_line = false +ij_groovy_class_annotation_wrap = split_into_lines +ij_groovy_class_brace_style = end_of_line +ij_groovy_class_count_to_use_import_on_demand = 5 +ij_groovy_do_while_brace_force = never +ij_groovy_else_on_new_line = false +ij_groovy_enum_constants_wrap = off +ij_groovy_extends_keyword_wrap = off +ij_groovy_extends_list_wrap = off +ij_groovy_field_annotation_wrap = split_into_lines +ij_groovy_finally_on_new_line = false +ij_groovy_for_brace_force = never +ij_groovy_for_statement_new_line_after_left_paren = false +ij_groovy_for_statement_right_paren_on_new_line = false +ij_groovy_for_statement_wrap = off +ij_groovy_if_brace_force = never +ij_groovy_import_annotation_wrap = 2 +ij_groovy_imports_layout = *,|,javax.**,java.**,|,$* +ij_groovy_indent_case_from_switch = true +ij_groovy_indent_label_blocks = true +ij_groovy_insert_inner_class_imports = false +ij_groovy_keep_blank_lines_before_right_brace = 2 +ij_groovy_keep_blank_lines_in_code = 2 +ij_groovy_keep_blank_lines_in_declarations = 2 +ij_groovy_keep_control_statement_in_one_line = true +ij_groovy_keep_first_column_comment = true +ij_groovy_keep_indents_on_empty_lines = false +ij_groovy_keep_line_breaks = true +ij_groovy_keep_multiple_expressions_in_one_line = false +ij_groovy_keep_simple_blocks_in_one_line = false +ij_groovy_keep_simple_classes_in_one_line = true +ij_groovy_keep_simple_lambdas_in_one_line = true +ij_groovy_keep_simple_methods_in_one_line = true +ij_groovy_label_indent_absolute = false +ij_groovy_label_indent_size = 0 +ij_groovy_lambda_brace_style = end_of_line +ij_groovy_layout_static_imports_separately = true +ij_groovy_line_comment_add_space = false +ij_groovy_line_comment_at_first_column = true +ij_groovy_method_annotation_wrap = split_into_lines +ij_groovy_method_brace_style = end_of_line +ij_groovy_method_call_chain_wrap = off +ij_groovy_method_parameters_new_line_after_left_paren = false +ij_groovy_method_parameters_right_paren_on_new_line = false +ij_groovy_method_parameters_wrap = off +ij_groovy_modifier_list_wrap = false +ij_groovy_names_count_to_use_import_on_demand = 3 +ij_groovy_parameter_annotation_wrap = off +ij_groovy_parentheses_expression_new_line_after_left_paren = false +ij_groovy_parentheses_expression_right_paren_on_new_line = false +ij_groovy_prefer_parameters_wrap = false +ij_groovy_resource_list_new_line_after_left_paren = false +ij_groovy_resource_list_right_paren_on_new_line = false +ij_groovy_resource_list_wrap = off +ij_groovy_space_after_assert_separator = true +ij_groovy_space_after_colon = true +ij_groovy_space_after_comma = true +ij_groovy_space_after_comma_in_type_arguments = true +ij_groovy_space_after_for_semicolon = true +ij_groovy_space_after_quest = true +ij_groovy_space_after_type_cast = true +ij_groovy_space_before_annotation_parameter_list = false +ij_groovy_space_before_array_initializer_left_brace = false +ij_groovy_space_before_assert_separator = false +ij_groovy_space_before_catch_keyword = true +ij_groovy_space_before_catch_left_brace = true +ij_groovy_space_before_catch_parentheses = true +ij_groovy_space_before_class_left_brace = true +ij_groovy_space_before_closure_left_brace = true +ij_groovy_space_before_colon = true +ij_groovy_space_before_comma = false +ij_groovy_space_before_do_left_brace = true +ij_groovy_space_before_else_keyword = true +ij_groovy_space_before_else_left_brace = true +ij_groovy_space_before_finally_keyword = true +ij_groovy_space_before_finally_left_brace = true +ij_groovy_space_before_for_left_brace = true +ij_groovy_space_before_for_parentheses = true +ij_groovy_space_before_for_semicolon = false +ij_groovy_space_before_if_left_brace = true +ij_groovy_space_before_if_parentheses = true +ij_groovy_space_before_method_call_parentheses = false +ij_groovy_space_before_method_left_brace = true +ij_groovy_space_before_method_parentheses = false +ij_groovy_space_before_quest = true +ij_groovy_space_before_switch_left_brace = true +ij_groovy_space_before_switch_parentheses = true +ij_groovy_space_before_synchronized_left_brace = true +ij_groovy_space_before_synchronized_parentheses = true +ij_groovy_space_before_try_left_brace = true +ij_groovy_space_before_try_parentheses = true +ij_groovy_space_before_while_keyword = true +ij_groovy_space_before_while_left_brace = true +ij_groovy_space_before_while_parentheses = true +ij_groovy_space_in_named_argument = true +ij_groovy_space_in_named_argument_before_colon = false +ij_groovy_space_within_empty_array_initializer_braces = false +ij_groovy_space_within_empty_method_call_parentheses = false +ij_groovy_spaces_around_additive_operators = true +ij_groovy_spaces_around_assignment_operators = true +ij_groovy_spaces_around_bitwise_operators = true +ij_groovy_spaces_around_equality_operators = true +ij_groovy_spaces_around_lambda_arrow = true +ij_groovy_spaces_around_logical_operators = true +ij_groovy_spaces_around_multiplicative_operators = true +ij_groovy_spaces_around_regex_operators = true +ij_groovy_spaces_around_relational_operators = true +ij_groovy_spaces_around_shift_operators = true +ij_groovy_spaces_within_annotation_parentheses = false +ij_groovy_spaces_within_array_initializer_braces = false +ij_groovy_spaces_within_braces = true +ij_groovy_spaces_within_brackets = false +ij_groovy_spaces_within_cast_parentheses = false +ij_groovy_spaces_within_catch_parentheses = false +ij_groovy_spaces_within_for_parentheses = false +ij_groovy_spaces_within_gstring_injection_braces = false +ij_groovy_spaces_within_if_parentheses = false +ij_groovy_spaces_within_list_or_map = false +ij_groovy_spaces_within_method_call_parentheses = false +ij_groovy_spaces_within_method_parentheses = false +ij_groovy_spaces_within_parentheses = false +ij_groovy_spaces_within_switch_parentheses = false +ij_groovy_spaces_within_synchronized_parentheses = false +ij_groovy_spaces_within_try_parentheses = false +ij_groovy_spaces_within_tuple_expression = false +ij_groovy_spaces_within_while_parentheses = false +ij_groovy_special_else_if_treatment = true +ij_groovy_ternary_operation_wrap = off +ij_groovy_throws_keyword_wrap = off +ij_groovy_throws_list_wrap = off +ij_groovy_use_flying_geese_braces = false +ij_groovy_use_fq_class_names = false +ij_groovy_use_fq_class_names_in_javadoc = true +ij_groovy_use_relative_indents = false +ij_groovy_use_single_class_imports = true +ij_groovy_variable_annotation_wrap = off +ij_groovy_while_brace_force = never +ij_groovy_while_on_new_line = false +ij_groovy_wrap_long_lines = false + +[{*.gradle.kts,*.kt,*.kts,*.main.kts}] +ij_kotlin_align_in_columns_case_branch = true +ij_kotlin_align_multiline_binary_operation = false +ij_kotlin_align_multiline_extends_list = false +ij_kotlin_align_multiline_method_parentheses = false +ij_kotlin_align_multiline_parameters = true +ij_kotlin_align_multiline_parameters_in_calls = false +ij_kotlin_allow_trailing_comma = false +ij_kotlin_allow_trailing_comma_on_call_site = false +ij_kotlin_assignment_wrap = off +ij_kotlin_blank_lines_after_class_header = 0 +ij_kotlin_blank_lines_around_block_when_branches = 0 +ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1 +ij_kotlin_block_comment_at_first_column = true +ij_kotlin_call_parameters_new_line_after_left_paren = false +ij_kotlin_call_parameters_right_paren_on_new_line = false +ij_kotlin_call_parameters_wrap = off +ij_kotlin_catch_on_new_line = false +ij_kotlin_class_annotation_wrap = off +ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL +ij_kotlin_continuation_indent_for_chained_calls = true +ij_kotlin_continuation_indent_for_expression_bodies = true +ij_kotlin_continuation_indent_in_argument_lists = true +ij_kotlin_continuation_indent_in_elvis = true +ij_kotlin_continuation_indent_in_if_conditions = true +ij_kotlin_continuation_indent_in_parameter_lists = true +ij_kotlin_continuation_indent_in_supertype_lists = true +ij_kotlin_else_on_new_line = false +ij_kotlin_enum_constants_wrap = off +ij_kotlin_extends_list_wrap = off +ij_kotlin_field_annotation_wrap = normal +ij_kotlin_finally_on_new_line = false +ij_kotlin_if_rparen_on_new_line = false +ij_kotlin_import_nested_classes = false +ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^ +ij_kotlin_insert_whitespaces_in_simple_one_line_method = true +ij_kotlin_keep_blank_lines_before_right_brace = 0 +ij_kotlin_keep_blank_lines_in_code = 1 +ij_kotlin_keep_blank_lines_in_declarations = 1 +ij_kotlin_keep_first_column_comment = true +ij_kotlin_keep_indents_on_empty_lines = false +ij_kotlin_keep_line_breaks = true +ij_kotlin_lbrace_on_next_line = false +ij_kotlin_line_comment_add_space = false +ij_kotlin_line_comment_at_first_column = true +ij_kotlin_method_annotation_wrap = split_into_lines +ij_kotlin_method_call_chain_wrap = off +ij_kotlin_method_parameters_new_line_after_left_paren = false +ij_kotlin_method_parameters_right_paren_on_new_line = false +ij_kotlin_method_parameters_wrap = off +ij_kotlin_name_count_to_use_star_import = 2147483647 +ij_kotlin_name_count_to_use_star_import_for_members = 2147483647 +ij_kotlin_packages_to_use_import_on_demand = kotlinx.android.synthetic.** +ij_kotlin_parameter_annotation_wrap = off +ij_kotlin_space_after_comma = true +ij_kotlin_space_after_extend_colon = true +ij_kotlin_space_after_type_colon = true +ij_kotlin_space_before_catch_parentheses = true +ij_kotlin_space_before_comma = false +ij_kotlin_space_before_extend_colon = true +ij_kotlin_space_before_for_parentheses = true +ij_kotlin_space_before_if_parentheses = true +ij_kotlin_space_before_lambda_arrow = true +ij_kotlin_space_before_type_colon = false +ij_kotlin_space_before_when_parentheses = true +ij_kotlin_space_before_while_parentheses = true +ij_kotlin_spaces_around_additive_operators = true +ij_kotlin_spaces_around_assignment_operators = true +ij_kotlin_spaces_around_equality_operators = true +ij_kotlin_spaces_around_function_type_arrow = true +ij_kotlin_spaces_around_logical_operators = true +ij_kotlin_spaces_around_multiplicative_operators = true +ij_kotlin_spaces_around_range = false +ij_kotlin_spaces_around_relational_operators = true +ij_kotlin_spaces_around_unary_operator = false +ij_kotlin_spaces_around_when_arrow = true +ij_kotlin_use_custom_formatting_for_modifiers = true +ij_kotlin_variable_annotation_wrap = off +ij_kotlin_while_on_new_line = false +ij_kotlin_wrap_elvis_expressions = 1 +ij_kotlin_wrap_expression_body_functions = 0 +ij_kotlin_wrap_first_method_in_call_chain = false + +[{*.har,*.json}] +indent_size = 2 +ij_json_keep_blank_lines_in_code = 0 +ij_json_keep_indents_on_empty_lines = false +ij_json_keep_line_breaks = true +ij_json_space_after_colon = true +ij_json_space_after_comma = true +ij_json_space_before_colon = true +ij_json_space_before_comma = false +ij_json_spaces_within_braces = false +ij_json_spaces_within_brackets = false +ij_json_wrap_long_lines = false + +[{*.htm,*.html,*.sht,*.shtm,*.shtml}] +ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3 +ij_html_align_attributes = true +ij_html_align_text = false +ij_html_attribute_wrap = normal +ij_html_block_comment_at_first_column = true +ij_html_do_not_align_children_of_min_lines = 0 +ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p +ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot +ij_html_enforce_quotes = false +ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var +ij_html_keep_blank_lines = 2 +ij_html_keep_indents_on_empty_lines = false +ij_html_keep_line_breaks = true +ij_html_keep_line_breaks_in_text = true +ij_html_keep_whitespaces = false +ij_html_keep_whitespaces_inside = span,pre,textarea +ij_html_line_comment_at_first_column = true +ij_html_new_line_after_last_attribute = never +ij_html_new_line_before_first_attribute = never +ij_html_quote_style = double +ij_html_remove_new_line_before_tags = br +ij_html_space_after_tag_name = false +ij_html_space_around_equality_in_attribute = false +ij_html_space_inside_empty_tag = false +ij_html_text_wrap = normal +ij_html_uniform_ident = false + +[{*.yaml,*.yml}] +indent_size = 2 +ij_yaml_align_values_properties = do_not_align +ij_yaml_autoinsert_sequence_marker = true +ij_yaml_block_mapping_on_new_line = false +ij_yaml_indent_sequence_value = true +ij_yaml_keep_indents_on_empty_lines = false +ij_yaml_keep_line_breaks = true +ij_yaml_sequence_on_new_line = false +ij_yaml_space_before_colon = false +ij_yaml_spaces_within_braces = true +ij_yaml_spaces_within_brackets = true diff --git a/.github/ISSUE_TEMPLATE/release.yml b/.github/ISSUE_TEMPLATE/release.yml index 582998d4922..c22b00e2e90 100644 --- a/.github/ISSUE_TEMPLATE/release.yml +++ b/.github/ISSUE_TEMPLATE/release.yml @@ -18,6 +18,7 @@ body: - [ ] Weblate sync, fix lint issue if any (in a dedicated PR) - [ ] Check the update of the store descriptions (using Google Translate if necessary) to ensure that the changes are acceptable to be published to the stores. + - [ ] While Weblate is locked, and after the PR from Weblate has been merged, handle all the TODOs in the main `strings.xml` file - [ ] Run the script `./tools/release/pushPlayStoreMetaData.sh`. You can check in the GooglePlay console the Activity log to check the effect. ### Do the release diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7096e6bdb5a..3940f2ca9e0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,7 +17,17 @@ ## Screenshots / GIFs - + + + ## Tests diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 14b5112818a..22b3a1727d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: - name: Assemble ${{ matrix.target }} debug apk run: ./gradlew assemble${{ matrix.target }}Debug $CI_GRADLE_ARG_PROPERTIES --stacktrace - name: Upload ${{ matrix.target }} debug APKs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: vector-${{ matrix.target }}-debug path: | @@ -61,7 +61,7 @@ jobs: - name: Assemble GPlay unsigned apk run: ./gradlew clean assembleGplayRelease $CI_GRADLE_ARG_PROPERTIES --stacktrace - name: Upload Gplay unsigned APKs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: vector-gplay-release-unsigned path: | diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b875a57abe5..84122095c6b 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -26,7 +26,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: gradle/wrapper-validation-action@v1 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'adopt' java-version: 11 @@ -43,7 +43,7 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Start synapse server - uses: michaelkaye/setup-matrix-synapse@v0.4.0 + uses: michaelkaye/setup-matrix-synapse@v1.0.1 with: uploadLogs: true httpPort: 8080 @@ -196,7 +196,7 @@ jobs: - `[org.matrix.android.sdk.PermalinkParserTest]`
${{ steps.get-comment-body-permalink.outputs.permalink }} edit-mode: replace - name: Upload Test Report Log - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: integrationtest-error-results @@ -230,12 +230,12 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Start synapse server - uses: michaelkaye/setup-matrix-synapse@v0.4.0 + uses: michaelkaye/setup-matrix-synapse@v1.0.1 with: uploadLogs: true httpPort: 8080 disableRateLimiting: true - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'adopt' java-version: '11' @@ -256,7 +256,7 @@ jobs: adb logcat >> emulator.log & ./gradlew $CI_GRADLE_ARG_PROPERTIES connectedGplayDebugAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=im.vector.app.ui.UiAllScreensSanityTest || (adb pull storage/emulated/0/Pictures/failure_screenshots && exit 1 ) - name: Upload Test Report Log - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: uitest-error-results @@ -269,7 +269,7 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'adopt' java-version: '11' @@ -283,7 +283,7 @@ jobs: ${{ runner.os }}-gradle- - run: ./gradlew allCodeCoverageReport $CI_GRADLE_ARG_PROPERTIES - name: Upload Codecov data - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: codecov-xml @@ -298,7 +298,7 @@ jobs: - codecov-units steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'adopt' java-version: '11' diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml index 934c14629e2..dee596980f8 100644 --- a/.github/workflows/quality.yml +++ b/.github/workflows/quality.yml @@ -29,7 +29,7 @@ jobs: ./gradlew ktlintCheck --continue - name: Upload reports if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ktlinting-report path: | @@ -109,7 +109,7 @@ jobs: run: ./gradlew clean :vector:lint --stacktrace - name: Upload reports if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: lint-report path: | @@ -142,7 +142,7 @@ jobs: run: ./gradlew clean lint${{ matrix.target }}Release --stacktrace - name: Upload ${{ matrix.target }} linting report if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: release-lint-report-${{ matrix.target }} path: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 98e5f588ca0..3e8de8979c8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,7 +21,7 @@ jobs: cancel-in-progress: true steps: - uses: actions/checkout@v3 - - uses: actions/setup-java@v2 + - uses: actions/setup-java@v3 with: distribution: 'adopt' java-version: 11 diff --git a/CHANGES.md b/CHANGES.md index 47b8c570411..4728994d772 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,65 @@ +Changes in Element v1.4.12 (2022-04-20) +======================================= + +Features ✨ +---------- + - Add a setting to be able to always appear offline ([#5582](https://github.com/vector-im/element-android/issues/5582)) + - Adds the ability for audio attachments to be played in the timeline ([#5586](https://github.com/vector-im/element-android/issues/5586)) + - Do not cancel the current incremental sync request and treatment when the app goes to background ([#5719](https://github.com/vector-im/element-android/issues/5719)) + - Improve user experience when home servers do not yet support threads ([#5761](https://github.com/vector-im/element-android/issues/5761)) + +Bugfixes 🐛 +---------- + - Added text next to spinner when loading information after user is clicked on space members screen ([#4305](https://github.com/vector-im/element-android/issues/4305)) + - The string `ftue_auth_carousel_workplace_body` was declared not translatable by mistake ([#5262](https://github.com/vector-im/element-android/issues/5262)) + - Fix some cases where the read marker line would not show up ([#5475](https://github.com/vector-im/element-android/issues/5475)) + - Fix sometimes read marker not properly updating ([#5481](https://github.com/vector-im/element-android/issues/5481)) + - Fix sometimes endless loading timeline ([#5554](https://github.com/vector-im/element-android/issues/5554)) + - Use member name instead of room name in DM creation item ([#5570](https://github.com/vector-im/element-android/issues/5570)) + - Align auto-reporting of decryption errors implementation with web client. ([#5596](https://github.com/vector-im/element-android/issues/5596)) + - Choosing "leave all rooms and spaces" while leaving Space won't cause leaving DMs in this Space anymore ([#5609](https://github.com/vector-im/element-android/issues/5609)) + - Fixes display name being changed when using /myroomnick ([#5618](https://github.com/vector-im/element-android/issues/5618)) + - Fix endless loading if the event from a permalink is not found ([#5659](https://github.com/vector-im/element-android/issues/5659)) + - Redacted events are no longer visible. ([#5707](https://github.com/vector-im/element-android/issues/5707)) + - Don't wrongly show non-space invites in the space panel. ([#5731](https://github.com/vector-im/element-android/issues/5731)) + - Fixes the onboarding confetti rendering behind the content instead of in-front ([#5735](https://github.com/vector-im/element-android/issues/5735)) + - Fixes crash when navigating the app whilst processing new room keys ([#5746](https://github.com/vector-im/element-android/issues/5746)) + - Fix sorting of uploads in encrypted rooms ([#5757](https://github.com/vector-im/element-android/issues/5757)) + - Fixing setting transfer title in call transfer. ([#5765](https://github.com/vector-im/element-android/issues/5765)) + - Changes destination after joining a space to Explore Space Rooms screen ([#5766](https://github.com/vector-im/element-android/issues/5766)) + - Unignoring a user will perform an initial sync ([#5767](https://github.com/vector-im/element-android/issues/5767)) + - Open a room by link: use the actual roomId instead of the alias ([#5786](https://github.com/vector-im/element-android/issues/5786)) + +In development 🚧 +---------------- + - FTUE - Adds a new homeserver selection screen when creating an account ([#2396](https://github.com/vector-im/element-android/issues/2396)) + - FTUE - Updates the Captcha and T&Cs registration screens UI style ([#5279](https://github.com/vector-im/element-android/issues/5279)) + - FTUE - Adds error handling within the server selection screen ([#5749](https://github.com/vector-im/element-android/issues/5749)) + - Live Location Sharing - Send location data ([#5697](https://github.com/vector-im/element-android/issues/5697)) + - Live Location Sharing - Show message on start of a live ([#5710](https://github.com/vector-im/element-android/issues/5710)) + - Live Location Sharing - Attach location data to beacon info state event ([#5711](https://github.com/vector-im/element-android/issues/5711)) + - Live Location Sharing - Update beacon info state event when sharing is ended ([#5758](https://github.com/vector-im/element-android/issues/5758)) + + +SDK API changes ⚠️ +------------------ + - Include original event in live decryption listeners and update sync status naming to InitialSyncProgressing for clarity. ([#5639](https://github.com/vector-im/element-android/issues/5639)) + - KeysBackupService.getCurrentVersion takes a new type `KeysBackupLastVersionResult` in the callback. ([#5703](https://github.com/vector-im/element-android/issues/5703)) + - A lot of classes which were exposed to the clients and were located in the package `org.matrix.android.sdk.internal` have been moved to the package `org.matrix.android.sdk.api`. + All the classes which are in the package `org.matrix.android.sdk.internal` should now be declared `internal`. + Some unused code and classes have been removed. ([#5744](https://github.com/vector-im/element-android/issues/5744)) + - Some data classes are now immutable, using `val` instead of `var` ([#5762](https://github.com/vector-im/element-android/issues/5762)) + +Other changes +------------- + - Upgrade konfetti lib from 1.3.2 to 2.0.2 ([#5079](https://github.com/vector-im/element-android/issues/5079)) + - Spaces feedback section is removed from left panel ([#5486](https://github.com/vector-im/element-android/issues/5486)) + - Reduce error logs ([#5703](https://github.com/vector-im/element-android/issues/5703)) + - Adds a complete editor config file for our current code style ([#5727](https://github.com/vector-im/element-android/issues/5727)) + - Updates the posthog dev environment url and api key ([#5732](https://github.com/vector-im/element-android/issues/5732)) + - Setup Dokka to be able to generate documentation of the SDK module. Run `./gradlew matrix-sdk-android:dokkaHtml` to do it. ([#5744](https://github.com/vector-im/element-android/issues/5744)) + + Changes in Element v1.4.11 (2022-04-07) ======================================= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f3739be08d3..053931cac57 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -144,6 +144,8 @@ Instead, please comment the original string with: ```xml ``` +And add `tools:ignore="UnusedResources"` to the string, to let lint ignore that the string is not used. + The string will be removed during the next sync with Weblate. ### Accessibility diff --git a/build.gradle b/build.gradle index 352b82c457b..1ff1da74278 100644 --- a/build.gradle +++ b/build.gradle @@ -22,6 +22,7 @@ buildscript { classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' classpath "com.likethesalad.android:stem-plugin:2.0.0" classpath 'org.owasp:dependency-check-gradle:7.0.4.1' + classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.6.20" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -105,6 +106,12 @@ allprojects { // display the corresponding rule verbose = true disabledRules = [ + // TODO: Re-enable these 4 rules after reformatting project + "indent", + "experimental:argument-list-wrapping", + "max-line-length", + "parameter-list-wrapping", + "spacing-between-declarations-with-comments", "no-multi-spaces", "experimental:spacing-between-declarations-with-annotations", diff --git a/coverage.gradle b/coverage.gradle index 96881dfff2c..b62ce0b4a09 100644 --- a/coverage.gradle +++ b/coverage.gradle @@ -17,7 +17,7 @@ def initializeReport(report, projects, classExcludes) { projects.each { project -> switch (project) { case { project.plugins.hasPlugin("com.android.application") }: - androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/debug") + androidClassDirs.add("${project.buildDir}/tmp/kotlin-classes/gplayDebug") androidSourceDirs.add("${project.projectDir}/src/main/kotlin") androidSourceDirs.add("${project.projectDir}/src/main/java") break diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index 9e70a1de421..2c3f6a02192 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -50,6 +50,7 @@ ext.groups = [ 'com.beust', 'com.davemorrissey.labs', 'com.dropbox.core', + 'com.soywiz.korlibs.korte', 'com.facebook.fbjni', 'com.facebook.fresco', 'com.facebook.infer.annotation', @@ -59,6 +60,9 @@ ext.groups = [ 'com.fasterxml', 'com.fasterxml.jackson', 'com.fasterxml.jackson.core', + 'com.fasterxml.jackson.dataformat', + 'com.fasterxml.jackson.module', + 'com.fasterxml.woodstox', 'com.gabrielittner.threetenbp', 'com.getkeepsafe.relinker', 'com.github.bumptech.glide', @@ -157,12 +161,14 @@ ext.groups = [ 'org.codehaus', 'org.codehaus.groovy', 'org.codehaus.mojo', + 'org.codehaus.woodstox', 'org.eclipse.ee4j', 'org.ec4j.core', 'org.glassfish.jaxb', 'org.hamcrest', 'org.jacoco', 'org.jetbrains', + 'org.jetbrains.dokka', 'org.jetbrains.intellij.deps', 'org.jetbrains.kotlin', 'org.jetbrains.kotlinx', @@ -208,4 +214,3 @@ ext.groups = [ ] ] ] - diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104060.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104060.txt new file mode 100644 index 00000000000..3eda0224644 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Časová osa vláken je nyní živá a rychlejší. Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104070.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104070.txt new file mode 100644 index 00000000000..cba2012c1cc --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/cs-CZ/changelogs/40104080.txt b/fastlane/metadata/android/cs-CZ/changelogs/40104080.txt new file mode 100644 index 00000000000..61e7fd79407 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Hlavní změny v této verzi: Časová osa vlákna je nyní živá a rychlejší. Opravy různých chyb a vylepšení stability. +Úplný seznam změn: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/en-US/changelogs/40104120.txt b/fastlane/metadata/android/en-US/changelogs/40104120.txt new file mode 100644 index 00000000000..ea188c101c5 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/40104120.txt @@ -0,0 +1,2 @@ +Main changes in this version: Allows users to appear offline and adds an audio player for audio attachments +Full changelog: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/et/changelogs/40104060.txt b/fastlane/metadata/android/et/changelogs/40104060.txt new file mode 100644 index 00000000000..f506b617ede --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: jutulõngad on nüüd kasutatavad ja toimivad kiiremini, lisaks pisiparandused ja stabiilsust parandavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/et/changelogs/40104070.txt b/fastlane/metadata/android/et/changelogs/40104070.txt new file mode 100644 index 00000000000..ea3582678d4 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: pisiparandused ja stabiilsust parandavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/et/changelogs/40104080.txt b/fastlane/metadata/android/et/changelogs/40104080.txt new file mode 100644 index 00000000000..a35fded9b60 --- /dev/null +++ b/fastlane/metadata/android/et/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Põhilised muutused selles versioonis: jutulõngad on nüüd kasutatavad ja toimivad kiiremini, lisaks pisiparandused ja stabiilsust parandavad kohendused. +Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fa/changelogs/40104060.txt b/fastlane/metadata/android/fa/changelogs/40104060.txt new file mode 100644 index 00000000000..5a1188b370f --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104060.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: خط زمانی رشته‌ها اکنون زنده و سریع‌تر است. چندین رفع اشکال و بهبود پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/fa/changelogs/40104070.txt b/fastlane/metadata/android/fa/changelogs/40104070.txt new file mode 100644 index 00000000000..d35ded337bb --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104070.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: چندین رفع اشکال و بهبود پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/fa/changelogs/40104080.txt b/fastlane/metadata/android/fa/changelogs/40104080.txt new file mode 100644 index 00000000000..673a46a10d7 --- /dev/null +++ b/fastlane/metadata/android/fa/changelogs/40104080.txt @@ -0,0 +1,2 @@ +تغییرات عمده در این نگارش: خط زمانی رشته‌ها اکنون زنده و سریع‌تر است. چندین رفع اشکال و بهبود پایداری. +گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104040.txt b/fastlane/metadata/android/fr-FR/changelogs/40104040.txt new file mode 100644 index 00000000000..af2d7bb0869 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104040.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Mise-à-jour de l’interface de notification de rédaction en cours. Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.4.4 diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104060.txt b/fastlane/metadata/android/fr-FR/changelogs/40104060.txt new file mode 100644 index 00000000000..24e0fde3f30 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Les fils de discussion sont officiellement disponibles, et plus rapides. Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104070.txt b/fastlane/metadata/android/fr-FR/changelogs/40104070.txt new file mode 100644 index 00000000000..3f9879d9174 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/fr-FR/changelogs/40104080.txt b/fastlane/metadata/android/fr-FR/changelogs/40104080.txt new file mode 100644 index 00000000000..84f92c18e21 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Principaux changements pour cette version : Les fils de discussion sont officiellement disponibles, et plus rapides. Plusieurs corrections de bogues et d’améliorations de stabilité. +Intégralité des changements : https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104040.txt b/fastlane/metadata/android/hu-HU/changelogs/40104040.txt new file mode 100644 index 00000000000..60ec5256aab --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104040.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: Gépelés visszajelzési frissítések a felületen. További hibajavítások egy stabilitást növelő fejlesztések. +Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.4.4 diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104060.txt b/fastlane/metadata/android/hu-HU/changelogs/40104060.txt new file mode 100644 index 00000000000..a3f4b89d926 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: Megjelentek az üzenetszálak az idővonalon és gyorsak. További hibajavítások és stabilitási fejlesztések. +Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104070.txt b/fastlane/metadata/android/hu-HU/changelogs/40104070.txt new file mode 100644 index 00000000000..0f969fb5772 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: Hibajavítások és stabilizációs fejlesztések. +Teljes változásnapló: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/hu-HU/changelogs/40104080.txt b/fastlane/metadata/android/hu-HU/changelogs/40104080.txt new file mode 100644 index 00000000000..c29b20c2160 --- /dev/null +++ b/fastlane/metadata/android/hu-HU/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Fő változás ebben a verzióban: Megjelentek az üzenetszálak az idővonalon és gyorsak. További hibajavítások és stabilitási fejlesztések. +Teljes változásnapló: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/id/changelogs/40104060.txt b/fastlane/metadata/android/id/changelogs/40104060.txt new file mode 100644 index 00000000000..3b4ce82497a --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Linimasa utasan sekarang langsung dan lebih cepat. Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/id/changelogs/40104070.txt b/fastlane/metadata/android/id/changelogs/40104070.txt new file mode 100644 index 00000000000..39daf31eb69 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/id/changelogs/40104080.txt b/fastlane/metadata/android/id/changelogs/40104080.txt new file mode 100644 index 00000000000..0a5ae820967 --- /dev/null +++ b/fastlane/metadata/android/id/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Perubahan utama dalam versi ini: Linimasa utasan sekarang langsung dan lebih cepat. Banyak perbaikan kutu dan perbaikan stabilitas. +Catatan perubahan lanjutan: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/it-IT/changelogs/40104060.txt b/fastlane/metadata/android/it-IT/changelogs/40104060.txt new file mode 100644 index 00000000000..c9ea8af2cc3 --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: la linea temporale per argomenti è ora attiva e più veloce. Varie correzioni e miglioramenti. +Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/it-IT/changelogs/40104070.txt b/fastlane/metadata/android/it-IT/changelogs/40104070.txt new file mode 100644 index 00000000000..2dfd415920f --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: varie correzioni di errori e miglioramenti della stabilità. +Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/it-IT/changelogs/40104080.txt b/fastlane/metadata/android/it-IT/changelogs/40104080.txt new file mode 100644 index 00000000000..8427e3d3feb --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Modifiche principali in questa versione: la linea temporale per argomenti è ora attiva e più veloce. Varie correzioni e miglioramenti. +Cronologia completa: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103060.txt b/fastlane/metadata/android/pl-PL/changelogs/40103060.txt new file mode 100644 index 00000000000..9dc1e9e297c --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103060.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Dodanie obsługi obecności, dla pokoju wiadomości bezpośrednich (uwaga: obecność jest wyłączona na matrix.org). Dodano ponownie obsługę Android Auto. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.6 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103070.txt b/fastlane/metadata/android/pl-PL/changelogs/40103070.txt index 2cb20a95707..08d9d2193ed 100644 --- a/fastlane/metadata/android/pl-PL/changelogs/40103070.txt +++ b/fastlane/metadata/android/pl-PL/changelogs/40103070.txt @@ -1,2 +1,2 @@ -Główne zmiany w tej wersji: Poprawki błędów dotyczące głównie powiadomień -Pełny changelog: https://github.com/vector-im/element-android/releases/tag/v1.3.7 +Główne zmiany w tej wersji: Poprawki błędów dotyczące głównie powiadomień. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.7-RC2 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103080.txt b/fastlane/metadata/android/pl-PL/changelogs/40103080.txt new file mode 100644 index 00000000000..c850479f590 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103080.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Poprawki błędów! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.8 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103090.txt b/fastlane/metadata/android/pl-PL/changelogs/40103090.txt new file mode 100644 index 00000000000..13e1aed51ed --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103090.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Dodano obsługę wersji roboczej wiadomości głosowych. Wiele poprawek! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.9 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103100.txt b/fastlane/metadata/android/pl-PL/changelogs/40103100.txt new file mode 100644 index 00000000000..406f07f70fd --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103100.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Dodano obsługę ankiet (w laboratoriach). Nowy projekt podglądu adresu URL. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.10 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103110.txt b/fastlane/metadata/android/pl-PL/changelogs/40103110.txt new file mode 100644 index 00000000000..f9b38673c75 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103110.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Poprawki błędów! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.11 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103120.txt b/fastlane/metadata/android/pl-PL/changelogs/40103120.txt new file mode 100644 index 00000000000..db6c1c86bd3 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103120.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Poprawki błędów! +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.12 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103130.txt b/fastlane/metadata/android/pl-PL/changelogs/40103130.txt new file mode 100644 index 00000000000..affd085177b --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103130.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Pierwsza zmiana na ekranach rejestracji, w tym możliwość włączenia Analytics. Dodano obsługę dla wydarzeń z dodatkiem matematyki w laboratoriach. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.13 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103140.txt b/fastlane/metadata/android/pl-PL/changelogs/40103140.txt new file mode 100644 index 00000000000..0727d3b4ff8 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103140.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Pierwsza zmiana na ekranach rejestracji, w tym możliwość włączenia Analytics. Dodano obsługę dla wydarzeń z dodatkiem matematyki w laboratoriach. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.14 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103150.txt b/fastlane/metadata/android/pl-PL/changelogs/40103150.txt new file mode 100644 index 00000000000..48d6d0feb31 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103150.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Pierwsza zmiana na ekranach rejestracji, w tym możliwość włączenia Analytics. Dodano obsługę dla wydarzeń z dodatkiem matematyki w laboratoriach. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.15 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103160.txt b/fastlane/metadata/android/pl-PL/changelogs/40103160.txt new file mode 100644 index 00000000000..df66e3042a3 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103160.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: wyślij swoją lokalizację do dowolnego pokoju. Edytuj ankietę. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.16 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103170.txt b/fastlane/metadata/android/pl-PL/changelogs/40103170.txt new file mode 100644 index 00000000000..77d40898a6e --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103170.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: wyślij swoją lokalizację do dowolnego pokoju. Edytuj ankietę. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.17 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40103180.txt b/fastlane/metadata/android/pl-PL/changelogs/40103180.txt new file mode 100644 index 00000000000..c0f671a58ec --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40103180.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: wyślij swoją lokalizację do dowolnego pokoju. Edytuj ankietę. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.3.18 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104000.txt b/fastlane/metadata/android/pl-PL/changelogs/40104000.txt new file mode 100644 index 00000000000..f9f4c80cf91 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104000.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Wstępna implementacja komunikatów wątków. Bąbelki wiadomości. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.4.0 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104020.txt b/fastlane/metadata/android/pl-PL/changelogs/40104020.txt new file mode 100644 index 00000000000..190427d548f --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104020.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: dodanie obsługi @room i nieujawnionych ankiet, i wiele innych drobnych zmian. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.4.2 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104040.txt b/fastlane/metadata/android/pl-PL/changelogs/40104040.txt new file mode 100644 index 00000000000..9894e54c036 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104040.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: aktualizacje interfejsu użytkownika wskaźnika pisania. Różne poprawki błędów i ulepszenia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.4.4 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104060.txt b/fastlane/metadata/android/pl-PL/changelogs/40104060.txt new file mode 100644 index 00000000000..216842ada06 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Oś czasu wątku jest teraz aktywna i szybsza. Różne poprawki błędów i ulepszenia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104070.txt b/fastlane/metadata/android/pl-PL/changelogs/40104070.txt new file mode 100644 index 00000000000..91c13d3d799 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Różne poprawki błędów i ulepszenia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/pl-PL/changelogs/40104080.txt b/fastlane/metadata/android/pl-PL/changelogs/40104080.txt new file mode 100644 index 00000000000..5286f40de5b --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Główne zmiany w tej wersji: Oś czasu wątku jest teraz aktywna i szybsza. Różne poprawki błędów i ulepszenia stabilności. +Pełna lista zmian: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104060.txt b/fastlane/metadata/android/pt-BR/changelogs/40104060.txt new file mode 100644 index 00000000000..17d8225c0da --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Timeline de Thread estão agora ao vivo e mais rápidas. Vários consertos de bugs e melhorias de estabilidade. +Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104070.txt b/fastlane/metadata/android/pt-BR/changelogs/40104070.txt new file mode 100644 index 00000000000..fad9bfe739c --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Vários consertos de bugs e melhorias de estabilidade. +Changelog completo: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/pt-BR/changelogs/40104080.txt b/fastlane/metadata/android/pt-BR/changelogs/40104080.txt new file mode 100644 index 00000000000..ca2b54f2f25 --- /dev/null +++ b/fastlane/metadata/android/pt-BR/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Principais mudanças nesta versão: Timeline de Thread estão agora ao vivo e mais rápidas. Vários consertos de bugs e melhorias de estabilidade. +Changelog completo: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sk/changelogs/40104060.txt b/fastlane/metadata/android/sk/changelogs/40104060.txt new file mode 100644 index 00000000000..53e192fe7c7 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Vlákna na časovej osi sú teraz živé a rýchlejšie. Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/sk/changelogs/40104070.txt b/fastlane/metadata/android/sk/changelogs/40104070.txt new file mode 100644 index 00000000000..1e056cf32f8 --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/sk/changelogs/40104080.txt b/fastlane/metadata/android/sk/changelogs/40104080.txt new file mode 100644 index 00000000000..7f42250fb9c --- /dev/null +++ b/fastlane/metadata/android/sk/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Hlavné zmeny v tejto verzii: Vlákna na časovej osi sú teraz živé a rýchlejšie. Rôzne opravy chýb a vylepšenia stability. +Úplný zoznam zmien: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sq/changelogs/40104060.txt b/fastlane/metadata/android/sq/changelogs/40104060.txt new file mode 100644 index 00000000000..48cbd2150c5 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Vijat kohore të rrjedhave tani janë në punë dhe më të shpejta. Ndreqje të metash të ndryshme dhe përmirësime qëndrueshmërie. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/sq/changelogs/40104070.txt b/fastlane/metadata/android/sq/changelogs/40104070.txt new file mode 100644 index 00000000000..ad487c57ee0 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Ndreqje të metash të ndryshme dhe përmirësime qëndrueshmërie. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/sq/changelogs/40104080.txt b/fastlane/metadata/android/sq/changelogs/40104080.txt new file mode 100644 index 00000000000..49156d0c965 --- /dev/null +++ b/fastlane/metadata/android/sq/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Ndryshimet kryesore në këtë version: Vijat kohore të rrjedhave tani janë në punë dhe më të shpejta. Ndreqje të metash të ndryshme dhe përmirësime qëndrueshmërie. +Regjistër i plotë ndryshimesh: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104060.txt b/fastlane/metadata/android/sv-SE/changelogs/40104060.txt new file mode 100644 index 00000000000..16a49fa3bc1 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Trådtidslinje är nu live och snabbare. Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104070.txt b/fastlane/metadata/android/sv-SE/changelogs/40104070.txt new file mode 100644 index 00000000000..01f79e85d6c --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/sv-SE/changelogs/40104080.txt b/fastlane/metadata/android/sv-SE/changelogs/40104080.txt new file mode 100644 index 00000000000..2ac7df2cdab --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Huvudsakliga ändringar i den här versionen: Trådtidslinje är nu live och snabbare. Diverse buggfixar och stabilitetsförbättringar. +Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.4.8 diff --git a/fastlane/metadata/android/uk/changelogs/40104060.txt b/fastlane/metadata/android/uk/changelogs/40104060.txt new file mode 100644 index 00000000000..28f051724ae --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104060.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/uk/changelogs/40104070.txt b/fastlane/metadata/android/uk/changelogs/40104070.txt new file mode 100644 index 00000000000..dff28b78256 --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104070.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/uk/changelogs/40104080.txt b/fastlane/metadata/android/uk/changelogs/40104080.txt new file mode 100644 index 00000000000..e5f7e7b271b --- /dev/null +++ b/fastlane/metadata/android/uk/changelogs/40104080.txt @@ -0,0 +1,2 @@ +Основні зміни в цій версії: Хронологія тредів працює наживо і швидше. Усунуто різні вади й поліпшено стабільність. +Вичерпний перелік змін: https://github.com/vector-im/element-android/releases diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104060.txt b/fastlane/metadata/android/zh-TW/changelogs/40104060.txt new file mode 100644 index 00000000000..316fad33631 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104060.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:討論串時間軸現已更新,而且更快了。多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.4.6 diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104070.txt b/fastlane/metadata/android/zh-TW/changelogs/40104070.txt new file mode 100644 index 00000000000..2cd9da666e8 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104070.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases/tag/v1.4.7 diff --git a/fastlane/metadata/android/zh-TW/changelogs/40104080.txt b/fastlane/metadata/android/zh-TW/changelogs/40104080.txt new file mode 100644 index 00000000000..c036aa7d563 --- /dev/null +++ b/fastlane/metadata/android/zh-TW/changelogs/40104080.txt @@ -0,0 +1,2 @@ +此版本中的主要變動:討論串時間軸現已更新,而且更快了。多個臭蟲修復與穩定性改善。 +完整的變更紀錄:https://github.com/vector-im/element-android/releases diff --git a/library/core-utils/src/main/java/im/vector/lib/core/utils/flow/TimingOperators.kt b/library/core-utils/src/main/java/im/vector/lib/core/utils/flow/TimingOperators.kt index 065c19c17ab..2efb439acef 100644 --- a/library/core-utils/src/main/java/im/vector/lib/core/utils/flow/TimingOperators.kt +++ b/library/core-utils/src/main/java/im/vector/lib/core/utils/flow/TimingOperators.kt @@ -25,7 +25,6 @@ import kotlinx.coroutines.channels.produce import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.consumeAsFlow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.isActive diff --git a/library/diff-match-patch/src/main/java/name/fraser/neil/plaintext/diff_match_patch.java b/library/diff-match-patch/src/main/java/name/fraser/neil/plaintext/diff_match_patch.java index 9d07867de5b..484fb38b489 100644 --- a/library/diff-match-patch/src/main/java/name/fraser/neil/plaintext/diff_match_patch.java +++ b/library/diff-match-patch/src/main/java/name/fraser/neil/plaintext/diff_match_patch.java @@ -21,7 +21,15 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; -import java.util.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/library/ui-styles/src/main/res/color/checkbox_tint_selector.xml b/library/ui-styles/src/main/res/color/checkbox_tint_selector.xml new file mode 100644 index 00000000000..67e2e685705 --- /dev/null +++ b/library/ui-styles/src/main/res/color/checkbox_tint_selector.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt index 72493325c3f..d21e898c1da 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowExt.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 New Vector Ltd + * Copyright (c) 2021 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt index 669e27edfdb..18753f07052 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/FlowSession.kt @@ -23,6 +23,9 @@ import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.group.GroupSummaryQueryParams import org.matrix.android.sdk.api.session.group.model.GroupSummary import org.matrix.android.sdk.api.session.identity.ThreePid @@ -39,9 +42,6 @@ import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.session.widgets.model.Widget import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo class FlowSession(private val session: Session) { diff --git a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt index a9f062f3793..42d84ed535a 100644 --- a/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt +++ b/matrix-sdk-android-flow/src/main/java/org/matrix/android/sdk/flow/OptionalFlow.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 New Vector Ltd + * Copyright (c) 2021 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/matrix-sdk-android/build.gradle b/matrix-sdk-android/build.gradle index 788fdaff551..0cffa4148ee 100644 --- a/matrix-sdk-android/build.gradle +++ b/matrix-sdk-android/build.gradle @@ -3,6 +3,7 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-parcelize' apply plugin: 'realm-android' +apply plugin: "org.jetbrains.dokka" buildscript { repositories { @@ -31,7 +32,7 @@ android { // that the app's state is completely cleared between tests. testInstrumentationRunnerArguments clearPackageData: 'true' - buildConfigField "String", "SDK_VERSION", "\"1.4.11\"" + buildConfigField "String", "SDK_VERSION", "\"1.4.12\"" buildConfigField "String", "GIT_SDK_REVISION", "\"${gitRevision()}\"" buildConfigField "String", "GIT_SDK_REVISION_UNIX_DATE", "\"${gitRevisionUnixDate()}\"" @@ -73,6 +74,10 @@ android { kotlinOptions { jvmTarget = "11" + freeCompilerArgs += [ + // Disabled for now, there are too many errors. Could be handled in another dedicated PR + // '-Xexplicit-api=strict', // or warning + ] } sourceSets { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt index 71796192a8d..e3ab1a4921a 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/CryptoTestHelper.kt @@ -27,8 +27,12 @@ import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod @@ -42,10 +46,6 @@ import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo import java.util.UUID import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt index d0f0e231524..dc58339498c 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/common/TestMatrixComponent.kt @@ -26,6 +26,7 @@ import org.matrix.android.sdk.internal.di.MatrixModule import org.matrix.android.sdk.internal.di.MatrixScope import org.matrix.android.sdk.internal.di.NetworkModule import org.matrix.android.sdk.internal.raw.RawModule +import org.matrix.android.sdk.internal.settings.SettingsModule import org.matrix.android.sdk.internal.util.system.SystemModule @Component(modules = [ @@ -34,6 +35,7 @@ import org.matrix.android.sdk.internal.util.system.SystemModule NetworkModule::class, AuthModule::class, RawModule::class, + SettingsModule::class, SystemModule::class ]) @MatrixScope diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt index aaf779212b6..732f4f7dce2 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/AttachmentEncryptionTest.kt @@ -25,10 +25,10 @@ import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters +import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments -import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey import java.io.ByteArrayOutputStream import java.io.InputStream diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt index 41ec69cdc5c..38846831510 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/E2eeSanityTests.kt @@ -30,7 +30,13 @@ import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure @@ -43,12 +49,6 @@ import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent @RunWith(JUnit4::class) @FixMethodOrder(MethodSorters.JVM) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt index 46c1dacf782..aa9f09314fd 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/PreShareKeysTest.kt @@ -26,11 +26,11 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) @@ -90,7 +90,7 @@ class PreShareKeysTest : InstrumentedTest { // Just send a real message as test val sentEvent = testHelper.sendTextMessage(aliceSession.getRoom(e2eRoomID)!!, "Allo", 1).first() - assertEquals("Unexpected megolm session", megolmSessionId, sentEvent.root.content.toModel()?.sessionId,) + assertEquals("Unexpected megolm session", megolmSessionId, sentEvent.root.content.toModel()?.sessionId) testHelper.waitWithLatch { latch -> testHelper.retryPeriodicallyWithLatch(latch) { bobSession.getRoom(e2eRoomID)?.getTimelineEvent(sentEvent.eventId)?.root?.getClearType() == EventType.MESSAGE diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt index fb5d58b127f..83464305307 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/UnwedgingTest.kt @@ -32,6 +32,7 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent @@ -40,7 +41,6 @@ import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm import org.matrix.android.sdk.internal.crypto.store.db.serializeForRealm import org.matrix.olm.OlmSession diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/ExtensionsKtTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/ExtensionsKtTest.kt index 9fa7458ea77..936dc6a8720 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/ExtensionsKtTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/ExtensionsKtTest.kt @@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.crypto.crosssigning import org.amshove.kluent.shouldBeNull import org.amshove.kluent.shouldBeTrue import org.junit.Test +import org.matrix.android.sdk.api.util.fromBase64 @Suppress("SpellCheckingInspection") class ExtensionsKtTest { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt index a6e8f94c910..dc65cec187b 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/crosssigning/XSigningTest.kt @@ -34,12 +34,14 @@ import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse +import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerified +import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt index 060201d6245..84c9487e030 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/encryption/EncryptionTest.kt @@ -24,7 +24,9 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.room.Room import org.matrix.android.sdk.api.session.room.send.SendState @@ -33,8 +35,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent import java.util.concurrent.CountDownLatch @RunWith(AndroidJUnit4::class) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt index cd20ab477ca..5e271c69101 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/KeyShareTests.kt @@ -35,12 +35,20 @@ import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams @@ -48,14 +56,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.internal.crypto.GossipingRequestState -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestState -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import kotlin.coroutines.Continuation import kotlin.coroutines.resume @@ -112,7 +112,7 @@ class KeyShareTests : InstrumentedTest { var outGoingRequestId: String? = null - commonTestHelper.waitWithLatch { latch -> + commonTestHelper.waitWithLatch { latch -> commonTestHelper.retryPeriodicallyWithLatch(latch) { aliceSession2.cryptoService().getOutgoingRoomKeyRequests() .filter { req -> diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt index e8f6eea460e..55bb03278c7 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/gossiping/WithHeldTests.kt @@ -30,14 +30,14 @@ import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.MockOkHttpInterceptor import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent -import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode @RunWith(AndroidJUnit4::class) @FixMethodOrder(MethodSorters.JVM) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupScenarioData.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupScenarioData.kt index 864f3c12e44..45fdb9e1e30 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupScenarioData.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupScenarioData.kt @@ -24,10 +24,12 @@ import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrappe /** * Data class to store result of [KeysBackupTestHelper.createKeysBackupScenarioWithPassword] */ -data class KeysBackupScenarioData(val cryptoTestData: CryptoTestData, - val aliceKeys: List, - val prepareKeysBackupDataResult: PrepareKeysBackupDataResult, - val aliceSession2: Session) { +internal data class KeysBackupScenarioData( + val cryptoTestData: CryptoTestData, + val aliceKeys: List, + val prepareKeysBackupDataResult: PrepareKeysBackupDataResult, + val aliceSession2: Session +) { fun cleanUp(testHelper: CommonTestHelper) { cryptoTestData.cleanUp(testHelper) testHelper.signOutAndClose(aliceSession2) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt index 4c945662194..063c0c0ca39 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTest.kt @@ -29,21 +29,22 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.StepProgressListener +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.TestConstants import org.matrix.android.sdk.common.TestMatrixCallback -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import java.util.Collections import java.util.concurrent.CountDownLatch @@ -403,9 +404,9 @@ class KeysBackupTest : InstrumentedTest { assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) // - Retrieve the last version from the server - val keysVersionResult = testHelper.doSync { + val keysVersionResult = testHelper.doSync { testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it) - } + }.toKeysVersionResult() // - It must be the same assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version) @@ -463,9 +464,9 @@ class KeysBackupTest : InstrumentedTest { assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) // - Retrieve the last version from the server - val keysVersionResult = testHelper.doSync { + val keysVersionResult = testHelper.doSync { testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it) - } + }.toKeysVersionResult() // - It must be the same assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version) @@ -565,9 +566,9 @@ class KeysBackupTest : InstrumentedTest { assertTrue(testData.aliceSession2.cryptoService().keysBackupService().isEnabled) // - Retrieve the last version from the server - val keysVersionResult = testHelper.doSync { + val keysVersionResult = testHelper.doSync { testData.aliceSession2.cryptoService().keysBackupService().getCurrentVersion(it) - } + }.toKeysVersionResult() // - It must be the same assertEquals(testData.prepareKeysBackupDataResult.version, keysVersionResult!!.version) @@ -835,9 +836,9 @@ class KeysBackupTest : InstrumentedTest { keysBackupTestHelper.prepareAndCreateKeysBackupData(keysBackup) // Get key backup version from the homeserver - val keysVersionResult = testHelper.doSync { + val keysVersionResult = testHelper.doSync { keysBackup.getCurrentVersion(it) - } + }.toKeysVersionResult() // - Check the returned KeyBackupVersion is trusted val keysBackupVersionTrust = testHelper.doSync { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt index 592b798bcce..ac83cb88821 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupTestHelper.kt @@ -22,16 +22,16 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper import org.matrix.android.sdk.common.assertDictEquals import org.matrix.android.sdk.common.assertListEquals import org.matrix.android.sdk.internal.crypto.MegolmSessionData -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion import java.util.concurrent.CountDownLatch -class KeysBackupTestHelper( +internal class KeysBackupTestHelper( private val testHelper: CommonTestHelper, private val cryptoTestHelper: CryptoTestHelper) { diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt index 6aefe98f867..31bd3c9cce5 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/keysbackup/PrepareKeysBackupDataResult.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto.keysbackup -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo data class PrepareKeysBackupDataResult(val megolmBackupCreationInfo: MegolmBackupCreationInfo, val version: String) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt index 67f17727b12..d6baa4b1e0d 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/ssss/QuadSTests.kt @@ -27,6 +27,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest +import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent @@ -37,11 +38,10 @@ import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageError import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.SessionTestParams import org.matrix.android.sdk.common.TestConstants -import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 -import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService @RunWith(AndroidJUnit4::class) diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt index 8cd725504d3..14e659e2b60 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/crypto/verification/SASTest.kt @@ -31,6 +31,8 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.OutgoingSasVerificationTransaction @@ -44,8 +46,6 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.common.CommonTestHelper import org.matrix.android.sdk.common.CryptoTestHelper -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationStart import org.matrix.android.sdk.internal.crypto.model.rest.toValue diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt index 1e3512a9df5..ef98ed22c71 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParserTest.kt @@ -27,6 +27,7 @@ import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest import org.matrix.android.sdk.api.MatrixConfiguration +import org.matrix.android.sdk.api.util.TextContent import org.matrix.android.sdk.common.TestRoomDisplayNameFallbackProvider import org.matrix.android.sdk.internal.session.displayname.DisplayNameResolver import org.matrix.android.sdk.internal.session.room.send.pills.MentionLinkSpecComparator diff --git a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt index 7ee6caed0da..6bcd12742b3 100644 --- a/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt +++ b/matrix-sdk-android/src/androidTest/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtilsTest.kt @@ -24,8 +24,8 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.matrix.android.sdk.InstrumentedTest -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding +import org.matrix.android.sdk.api.util.fromBase64 +import org.matrix.android.sdk.api.util.toBase64NoPadding import java.io.ByteArrayOutputStream import java.util.UUID diff --git a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/FormattedJsonHttpLogger.kt b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/FormattedJsonHttpLogger.kt index 34ed28d467a..2661bd1f70b 100644 --- a/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/FormattedJsonHttpLogger.kt +++ b/matrix-sdk-android/src/debug/java/org/matrix/android/sdk/internal/network/interceptors/FormattedJsonHttpLogger.kt @@ -23,7 +23,7 @@ import org.json.JSONException import org.json.JSONObject import timber.log.Timber -class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger { +internal class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger { companion object { private const val INDENT_SPACE = 2 diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/DisplayMaths.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/DisplayMaths.kt index b8ee36e7240..3e83594ca3a 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/DisplayMaths.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/DisplayMaths.kt @@ -17,7 +17,7 @@ package org.commonmark.ext.maths import org.commonmark.node.CustomBlock -class DisplayMaths(private val delimiter: DisplayDelimiter) : CustomBlock() { +internal class DisplayMaths(private val delimiter: DisplayDelimiter) : CustomBlock() { enum class DisplayDelimiter { DOUBLE_DOLLAR, SQUARE_BRACKET_ESCAPED diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt index 962b1b8cbf3..3fe8d156962 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/InlineMaths.kt @@ -18,7 +18,7 @@ package org.commonmark.ext.maths import org.commonmark.node.CustomNode import org.commonmark.node.Delimited -class InlineMaths(private val delimiter: InlineDelimiter) : CustomNode(), Delimited { +internal class InlineMaths(private val delimiter: InlineDelimiter) : CustomNode(), Delimited { enum class InlineDelimiter { SINGLE_DOLLAR, ROUND_BRACKET_ESCAPED diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/MathsExtension.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/MathsExtension.kt index 18c0fc4284b..7a53253bd68 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/MathsExtension.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/MathsExtension.kt @@ -21,7 +21,7 @@ import org.commonmark.ext.maths.internal.MathsHtmlNodeRenderer import org.commonmark.parser.Parser import org.commonmark.renderer.html.HtmlRenderer -class MathsExtension private constructor() : Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { +internal class MathsExtension private constructor() : Parser.ParserExtension, HtmlRenderer.HtmlRendererExtension { override fun extend(parserBuilder: Parser.Builder) { parserBuilder.customDelimiterProcessor(DollarMathsDelimiterProcessor()) } diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/DollarMathsDelimiterProcessor.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/DollarMathsDelimiterProcessor.kt index cfd03fa8f16..95ea1a1766f 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/DollarMathsDelimiterProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/DollarMathsDelimiterProcessor.kt @@ -21,7 +21,7 @@ import org.commonmark.node.Text import org.commonmark.parser.delimiter.DelimiterProcessor import org.commonmark.parser.delimiter.DelimiterRun -class DollarMathsDelimiterProcessor : DelimiterProcessor { +internal class DollarMathsDelimiterProcessor : DelimiterProcessor { override fun getOpeningCharacter() = '$' override fun getClosingCharacter() = '$' diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt index 94652ed7ad8..0efecbbe8a9 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsHtmlNodeRenderer.kt @@ -22,7 +22,7 @@ import org.commonmark.renderer.html.HtmlNodeRendererContext import org.commonmark.renderer.html.HtmlWriter import java.util.Collections -class MathsHtmlNodeRenderer(private val context: HtmlNodeRendererContext) : MathsNodeRenderer() { +internal class MathsHtmlNodeRenderer(private val context: HtmlNodeRendererContext) : MathsNodeRenderer() { private val html: HtmlWriter = context.writer override fun render(node: Node) { val display = node.javaClass == DisplayMaths::class.java diff --git a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsNodeRenderer.kt b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsNodeRenderer.kt index 55cdc05c398..6924a9fb54e 100644 --- a/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsNodeRenderer.kt +++ b/matrix-sdk-android/src/main/java/org/commonmark/ext/maths/internal/MathsNodeRenderer.kt @@ -19,9 +19,8 @@ import org.commonmark.ext.maths.DisplayMaths import org.commonmark.ext.maths.InlineMaths import org.commonmark.node.Node import org.commonmark.renderer.NodeRenderer -import java.util.HashSet -abstract class MathsNodeRenderer : NodeRenderer { +internal abstract class MathsNodeRenderer : NodeRenderer { override fun getNodeTypes(): Set> { val types: MutableSet> = HashSet() types.add(InlineMaths::class.java) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt index 5fedff53f0d..e7b4b766ade 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/Matrix.kt @@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.legacy.LegacySessionImporter import org.matrix.android.sdk.api.network.ApiInterceptorListener import org.matrix.android.sdk.api.network.ApiPath import org.matrix.android.sdk.api.raw.RawService +import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.di.DaggerMatrixComponent import org.matrix.android.sdk.internal.network.ApiInterceptor @@ -56,6 +57,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo @Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService @Inject internal lateinit var apiInterceptor: ApiInterceptor @Inject internal lateinit var matrixWorkerFactory: MatrixWorkerFactory + @Inject internal lateinit var lightweightSettingsStorage: LightweightSettingsStorage init { Monarchy.init(context) @@ -78,6 +80,8 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo fun rawService() = rawService + fun lightweightSettingsStorage() = lightweightSettingsStorage + fun homeServerHistoryService() = homeServerHistoryService fun legacySessionImporter(): LegacySessionImporter { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt index c4bc289b753..f8472319fdc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixConfiguration.kt @@ -61,10 +61,6 @@ data class MatrixConfiguration( * RoomDisplayNameFallbackProvider to provide default room display name. */ val roomDisplayNameFallbackProvider: RoomDisplayNameFallbackProvider, - /** - * True to enable presence information sync (if available). False to disable regardless of server setting. - */ - val presenceSyncEnabled: Boolean = true, /** * Thread messages default enable/disabled value */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/HomeServerHistoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/HomeServerHistoryService.kt index 77e33b8934d..6850bdd444f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/HomeServerHistoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/HomeServerHistoryService.kt @@ -20,10 +20,19 @@ package org.matrix.android.sdk.api.auth * A simple service to remember homeservers you already connected to. */ interface HomeServerHistoryService { - + /** + * Get a list of stored homeserver urls. + */ fun getKnownServersUrls(): List + /** + * Add a homeserver url to the list of stored homeserver urls. + * Will not be added again if already present in the list. + */ fun addHomeServerToHistory(url: String) + /** + * Delete the list of stored homeserver urls. + */ fun clearHistory() } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt index 434e4a6e2ed..317acccfb51 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/Credentials.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.auth.data import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.util.md5 +import org.matrix.android.sdk.api.util.md5 /** * This data class hold credentials user data. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt index e87824d6a5f..c2c1f043bbf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/HomeServerConnectionConfig.kt @@ -22,7 +22,7 @@ import okhttp3.CipherSuite import okhttp3.ConnectionSpec import okhttp3.TlsVersion import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder -import org.matrix.android.sdk.internal.network.ssl.Fingerprint +import org.matrix.android.sdk.api.network.ssl.Fingerprint import org.matrix.android.sdk.internal.util.ensureTrailingSlash /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/LocalizedFlowDataLoginTerms.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LocalizedFlowDataLoginTerms.kt similarity index 79% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/LocalizedFlowDataLoginTerms.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LocalizedFlowDataLoginTerms.kt index 5d119bb6177..1e844a1d947 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/LocalizedFlowDataLoginTerms.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/data/LocalizedFlowDataLoginTerms.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.auth.registration +package org.matrix.android.sdk.api.auth.data import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -24,8 +24,8 @@ import kotlinx.parcelize.Parcelize */ @Parcelize data class LocalizedFlowDataLoginTerms( - var policyName: String? = null, - var version: String? = null, - var localizedUrl: String? = null, - var localizedName: String? = null + val policyName: String?, + val version: String?, + val localizedUrl: String?, + val localizedName: String? ) : Parcelable diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt index ac740ddab71..0da9eb4b7e1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/auth/registration/RegistrationFlowResponse.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.api.auth.registration import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import org.matrix.android.sdk.api.session.uia.InteractiveAuthenticationFlow import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.auth.data.InteractiveAuthenticationFlow @JsonClass(generateAdapter = true) data class RegistrationFlowResponse( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoConstants.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt index 96635b33d6f..172cfa83607 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CryptoConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/CryptoConstants.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.crypto /** * Matrix algorithm value for olm. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/MatrixSdkExtensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/MatrixSdkExtensions.kt index 1cdb6d49a53..f09e9bb340a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/MatrixSdkExtensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/extensions/MatrixSdkExtensions.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.api.extensions -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo /* ========================================================================================== * MXDeviceInfo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt index 89b4a343dd4..362ebcec26d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Extensions.kt @@ -22,29 +22,29 @@ import org.matrix.android.sdk.api.session.contentscanner.ContentScannerError import org.matrix.android.sdk.api.session.contentscanner.ScanFailure import org.matrix.android.sdk.internal.di.MoshiProvider import java.io.IOException +import java.net.UnknownHostException import javax.net.ssl.HttpsURLConnection -fun Throwable.is401() = - this is Failure.ServerError && - httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED && /* 401 */ - error.code == MatrixError.M_UNAUTHORIZED - -fun Throwable.isTokenError() = - this is Failure.ServerError && - (error.code == MatrixError.M_UNKNOWN_TOKEN || - error.code == MatrixError.M_MISSING_TOKEN || - error.code == MatrixError.ORG_MATRIX_EXPIRED_ACCOUNT) - -fun Throwable.isLimitExceededError() = - this is Failure.ServerError && - httpCode == 429 && - error.code == MatrixError.M_LIMIT_EXCEEDED - -fun Throwable.shouldBeRetried(): Boolean { - return this is Failure.NetworkConnection || - this is IOException || - this.isLimitExceededError() -} +fun Throwable.is401() = this is Failure.ServerError && + httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED && /* 401 */ + error.code == MatrixError.M_UNAUTHORIZED + +fun Throwable.is404() = this is Failure.ServerError && + httpCode == HttpsURLConnection.HTTP_NOT_FOUND && /* 404 */ + error.code == MatrixError.M_NOT_FOUND + +fun Throwable.isTokenError() = this is Failure.ServerError && + (error.code == MatrixError.M_UNKNOWN_TOKEN || + error.code == MatrixError.M_MISSING_TOKEN || + error.code == MatrixError.ORG_MATRIX_EXPIRED_ACCOUNT) + +fun Throwable.isLimitExceededError() = this is Failure.ServerError && + httpCode == 429 && + error.code == MatrixError.M_LIMIT_EXCEEDED + +fun Throwable.shouldBeRetried() = this is Failure.NetworkConnection || + this is IOException || + isLimitExceededError() /** * Get the retry delay in case of rate limit exceeded error, adding 100 ms, of defaultValue otherwise @@ -58,41 +58,33 @@ fun Throwable.getRetryDelay(defaultValue: Long): Long { ?: defaultValue } -fun Throwable.isUsernameInUse(): Boolean { - return this is Failure.ServerError && error.code == MatrixError.M_USER_IN_USE -} +fun Throwable.isUsernameInUse() = this is Failure.ServerError && + error.code == MatrixError.M_USER_IN_USE -fun Throwable.isInvalidUsername(): Boolean { - return this is Failure.ServerError && - error.code == MatrixError.M_INVALID_USERNAME -} +fun Throwable.isInvalidUsername() = this is Failure.ServerError && + error.code == MatrixError.M_INVALID_USERNAME -fun Throwable.isInvalidPassword(): Boolean { - return this is Failure.ServerError && - error.code == MatrixError.M_FORBIDDEN && - error.message == "Invalid password" -} +fun Throwable.isInvalidPassword() = this is Failure.ServerError && + error.code == MatrixError.M_FORBIDDEN && + error.message == "Invalid password" -fun Throwable.isRegistrationDisabled(): Boolean { - return this is Failure.ServerError && error.code == MatrixError.M_FORBIDDEN && - httpCode == HttpsURLConnection.HTTP_FORBIDDEN -} +fun Throwable.isRegistrationDisabled() = this is Failure.ServerError && + error.code == MatrixError.M_FORBIDDEN && + httpCode == HttpsURLConnection.HTTP_FORBIDDEN -fun Throwable.isWeakPassword(): Boolean { - return this is Failure.ServerError && error.code == MatrixError.M_WEAK_PASSWORD -} +fun Throwable.isWeakPassword() = this is Failure.ServerError && + error.code == MatrixError.M_WEAK_PASSWORD -fun Throwable.isLoginEmailUnknown(): Boolean { - return this is Failure.ServerError && - error.code == MatrixError.M_FORBIDDEN && - error.message.isEmpty() -} +fun Throwable.isLoginEmailUnknown() = this is Failure.ServerError && + error.code == MatrixError.M_FORBIDDEN && + error.message.isEmpty() -fun Throwable.isInvalidUIAAuth(): Boolean { - return this is Failure.ServerError && - error.code == MatrixError.M_FORBIDDEN && - error.flows != null -} +fun Throwable.isInvalidUIAAuth() = this is Failure.ServerError && + error.code == MatrixError.M_FORBIDDEN && + error.flows != null + +fun Throwable.isHomeserverUnavailable() = this is Failure.NetworkConnection && + this.ioException is UnknownHostException /** * Try to convert to a RegistrationFlowResponse. Return null in the cases it's not possible @@ -124,13 +116,11 @@ fun Throwable.toRegistrationFlowResponse(): RegistrationFlowResponse? { } } -fun Throwable.isRegistrationAvailabilityError(): Boolean { - return this is Failure.ServerError && - httpCode == HttpsURLConnection.HTTP_BAD_REQUEST && /* 400 */ - (error.code == MatrixError.M_USER_IN_USE || - error.code == MatrixError.M_INVALID_USERNAME || - error.code == MatrixError.M_EXCLUSIVE) -} +fun Throwable.isRegistrationAvailabilityError() = this is Failure.ServerError && + httpCode == HttpsURLConnection.HTTP_BAD_REQUEST && /* 400 */ + (error.code == MatrixError.M_USER_IN_USE || + error.code == MatrixError.M_INVALID_USERNAME || + error.code == MatrixError.M_EXCLUSIVE) /** * Try to convert to a ScanFailure. Return null in the cases it's not possible diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt index 8f1bbb69415..be139fd82bd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/Failure.kt @@ -17,8 +17,8 @@ package org.matrix.android.sdk.api.failure import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse +import org.matrix.android.sdk.api.network.ssl.Fingerprint import org.matrix.android.sdk.api.session.crypto.MXCryptoError -import org.matrix.android.sdk.internal.network.ssl.Fingerprint import java.io.IOException /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt index 50c84da02b8..b5165b6687d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/GlobalError.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.failure -import org.matrix.android.sdk.internal.network.ssl.Fingerprint +import org.matrix.android.sdk.api.network.ssl.Fingerprint // This class will be sent to the bus sealed class GlobalError { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt index 1bc8636103d..32e1aca17d8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/failure/MatrixError.kt @@ -18,8 +18,8 @@ package org.matrix.android.sdk.api.failure import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.uia.InteractiveAuthenticationFlow import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.auth.data.InteractiveAuthenticationFlow /** * This data class holds the error defined by the matrix specifications. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/Fingerprint.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/Fingerprint.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt index b096bd6c879..93e93fd2921 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/Fingerprint.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/network/ssl/Fingerprint.kt @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.network.ssl +package org.matrix.android.sdk.api.network.ssl import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.internal.network.ssl.CertUtil import java.security.cert.CertificateException import java.security.cert.X509Certificate diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/LiveEventListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/LiveEventListener.kt index 6fda65953ac..b4b283c86a2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/LiveEventListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/LiveEventListener.kt @@ -25,9 +25,9 @@ interface LiveEventListener { fun onPaginatedEvent(roomId: String, event: Event) - fun onEventDecrypted(eventId: String, roomId: String, clearEvent: JsonDict) + fun onEventDecrypted(event: Event, clearEvent: JsonDict) - fun onEventDecryptionError(eventId: String, roomId: String, throwable: Throwable) + fun onEventDecryptionError(event: Event, throwable: Throwable) fun onLiveToDeviceEvent(event: Event) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt index 45fd39fa954..d7afad5b6c4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/ToDeviceService.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.api.session +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.events.model.Content -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import java.util.UUID interface ToDeviceService { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt index 3dd096e1446..523d60359b0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/content/ContentUrlResolver.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.content -import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt /** * This interface defines methods for accessing content from the current session. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/contentscanner/ContentScannerService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/contentscanner/ContentScannerService.kt index 1dd7bab01c5..7a85a89058a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/contentscanner/ContentScannerService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/contentscanner/ContentScannerService.kt @@ -17,8 +17,8 @@ package org.matrix.android.sdk.api.session.contentscanner import androidx.lifecycle.LiveData +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt interface ContentScannerService { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt index a5b442dc4a7..d6d1248de78 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/CryptoService.kt @@ -23,25 +23,24 @@ import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult -import org.matrix.android.sdk.internal.crypto.NewSessionListener -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXEncryptEventContentResult -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent interface CryptoService { @@ -113,6 +112,7 @@ interface CryptoService { fun isRoomEncrypted(roomId: String): Boolean + // TODO This could be removed from this interface fun encryptEventContent(eventContent: Content, eventType: String, roomId: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt index 4956278a101..5ff4b54b110 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/MXCryptoError.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.api.session.crypto -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.olm.OlmException /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/NewSessionListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/NewSessionListener.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt index 9b39a8ab258..73cbf5fb78a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/NewSessionListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/NewSessionListener.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto + +package org.matrix.android.sdk.api.session.crypto /** * This listener notifies on new Megolm sessions being created diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/ElementToDecrypt.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/ElementToDecrypt.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt index 3d00e178a0c..de168ac6e52 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/ElementToDecrypt.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/attachments/ElementToDecrypt.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.attachments +package org.matrix.android.sdk.api.session.crypto.attachments import android.os.Parcelable import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo fun EncryptedFileInfo.toElementToDecrypt(): ElementToDecrypt? { // Check the validity of some fields diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt index 359e33cc2c6..46b131f613f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CrossSigningService.kt @@ -20,9 +20,6 @@ import androidx.lifecycle.LiveData import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustResult -import org.matrix.android.sdk.internal.crypto.crosssigning.UserTrustResult -import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo interface CrossSigningService { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoCrossSigningKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoCrossSigningKey.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt index 606d2e3fc0c..11996e673e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoCrossSigningKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/CryptoCrossSigningKey.kt @@ -14,9 +14,10 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model +package org.matrix.android.sdk.api.session.crypto.crosssigning -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.internal.crypto.model.CryptoInfo +import org.matrix.android.sdk.internal.crypto.model.CryptoInfoMapper import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo data class CryptoCrossSigningKey( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustLevel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustLevel.kt similarity index 87% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustLevel.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustLevel.kt index fa0098e4a40..a0ab5b3b95a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustLevel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustLevel.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.crosssigning +package org.matrix.android.sdk.api.session.crypto.crosssigning data class DeviceTrustLevel( val crossSigningVerified: Boolean, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustResult.kt similarity index 88% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustResult.kt index 6e7c620a031..777d34221f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DeviceTrustResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/DeviceTrustResult.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,9 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.crosssigning - -import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +package org.matrix.android.sdk.api.session.crypto.crosssigning sealed class DeviceTrustResult { data class Success(val level: DeviceTrustLevel) : DeviceTrustResult() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/MXCrossSigningInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/MXCrossSigningInfo.kt index 20ee68d228d..9604decd629 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/MXCrossSigningInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/MXCrossSigningInfo.kt @@ -16,9 +16,6 @@ package org.matrix.android.sdk.api.session.crypto.crosssigning -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.KeyUsage - data class MXCrossSigningInfo( val userId: String, val crossSigningKeys: List diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/PrivateKeysInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/PrivateKeysInfo.kt similarity index 92% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/PrivateKeysInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/PrivateKeysInfo.kt index 04793f185a9..f15d7dc598b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/PrivateKeysInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/PrivateKeysInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.store +package org.matrix.android.sdk.api.session.crypto.crosssigning data class PrivateKeysInfo( val master: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UserTrustResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/UserTrustResult.kt similarity index 83% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UserTrustResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/UserTrustResult.kt index 20e7ca09abd..7fc815cd20c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UserTrustResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/crosssigning/UserTrustResult.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,10 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.crosssigning - -import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey +package org.matrix.android.sdk.api.session.crypto.crosssigning sealed class UserTrustResult { object Success : UserTrustResult() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Try.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt similarity index 50% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Try.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt index 2ce0534b49b..a7e985cea97 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Try.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupLastVersionResult.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,27 +14,15 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.extensions +package org.matrix.android.sdk.api.session.crypto.keysbackup -import arrow.core.Failure -import arrow.core.Success -import arrow.core.Try -import arrow.core.TryOf -import arrow.core.fix - -inline fun TryOf.onError(f: (Throwable) -> Unit): Try = fix() - .fold( - { - f(it) - Failure(it) - }, - { Success(it) } - ) +sealed interface KeysBackupLastVersionResult { + // No Keys backup found (404 error) + object NoKeysBackup : KeysBackupLastVersionResult + data class KeysBackup(val keysVersionResult: KeysVersionResult) : KeysBackupLastVersionResult +} -/** - * Same as doOnNext for Observables - */ -inline fun Try.alsoDo(f: (A) -> Unit) = map { - f(it) - it +fun KeysBackupLastVersionResult.toKeysVersionResult(): KeysVersionResult? = when (this) { + is KeysBackupLastVersionResult.KeysBackup -> keysVersionResult + KeysBackupLastVersionResult.NoKeysBackup -> null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt index 4464427b903..9ff99f8dce1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupService.kt @@ -19,21 +19,16 @@ package org.matrix.android.sdk.api.session.crypto.keysbackup import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.StepProgressListener -import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult interface KeysBackupService { /** * Retrieve the current version of the backup from the homeserver * * It can be different than keysBackupVersion. - * @param callback onSuccess(null) will be called if there is no backup on the server + * @param callback Asynchronous callback */ - fun getCurrentVersion(callback: MatrixCallback) + fun getCurrentVersion(callback: MatrixCallback) /** * Create a new keys backup version and enable it, using the information return from [prepareKeysBackupVersion]. @@ -219,4 +214,9 @@ interface KeysBackupService { fun getKeyBackupRecoveryKeyInfo(): SavedKeyBackupKeyInfo? fun isValidRecoveryKeyForCurrentVersion(recoveryKey: String, callback: MatrixCallback) + + fun computePrivateKey(passphrase: String, + privateKeySalt: String, + privateKeyIterations: Int, + progressListener: ProgressListener): ByteArray } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrust.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrust.kt similarity index 83% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrust.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrust.kt index 497cb0eb490..c9a2d4e7a59 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrust.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrust.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model +package org.matrix.android.sdk.api.session.crypto.keysbackup /** * Data model for response to [KeysBackup.getKeysBackupTrust()]. @@ -24,10 +24,10 @@ data class KeysBackupVersionTrust( * Flag to indicate if the backup is trusted. * true if there is a signature that is valid & from a trusted device. */ - var usable: Boolean = false, + val usable: Boolean, /** * Signatures found in the backup version. */ - var signatures: MutableList = ArrayList() + val signatures: List = emptyList() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrustSignature.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt similarity index 53% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrustSignature.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt index 1e3db288826..219a328cfdd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeysBackupVersionTrustSignature.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysBackupVersionTrustSignature.kt @@ -14,28 +14,27 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model +package org.matrix.android.sdk.api.session.crypto.keysbackup -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo /** * A signature in a `KeysBackupVersionTrust` object. */ -class KeysBackupVersionTrustSignature { +data class KeysBackupVersionTrustSignature( + /** + * The id of the device that signed the backup version. + */ + val deviceId: String?, - /** - * The id of the device that signed the backup version. - */ - var deviceId: String? = null + /** + * The device that signed the backup version. + * Can be null if the device is not known. + */ + val device: CryptoDeviceInfo?, - /** - * The device that signed the backup version. - * Can be null if the device is not known. - */ - var device: CryptoDeviceInfo? = null - - /** - * Flag to indicate the signature from this device is valid. - */ - var valid = false -} + /** + * Flag to indicate the signature from this device is valid. + */ + val valid: Boolean, +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersion.kt similarity index 86% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersion.kt index 7a4c3415fc0..1dbfe84dff5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersion.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersion.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest +package org.matrix.android.sdk.api.session.crypto.keysbackup import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt index 485fd48a8cf..f283a34e98f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysVersionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/KeysVersionResult.kt @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest +package org.matrix.android.sdk.api.session.crypto.keysbackup import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysAlgorithmAndData @JsonClass(generateAdapter = true) data class KeysVersionResult( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupAuthData.kt similarity index 79% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupAuthData.kt index 17c895762c4..2a620af843c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupAuthData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupAuthData.kt @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model +package org.matrix.android.sdk.api.session.crypto.keysbackup import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData import org.matrix.android.sdk.internal.di.MoshiProvider /** @@ -54,7 +55,7 @@ data class MegolmBackupAuthData( val signatures: Map>? = null ) { - fun toJsonDict(): JsonDict { + internal fun toJsonDict(): JsonDict { val moshi = MoshiProvider.providesMoshi() val adapter = moshi.adapter(Map::class.java) @@ -67,7 +68,7 @@ data class MegolmBackupAuthData( } } - fun signalableJSONDictionary(): JsonDict { + internal fun signalableJSONDictionary(): JsonDict { return SignalableMegolmBackupAuthData( publicKey = publicKey, privateKeySalt = privateKeySalt, @@ -76,20 +77,3 @@ data class MegolmBackupAuthData( .signalableJSONDictionary() } } - -internal data class SignalableMegolmBackupAuthData( - val publicKey: String, - val privateKeySalt: String? = null, - val privateKeyIterations: Int? = null -) { - fun signalableJSONDictionary(): JsonDict = HashMap().apply { - put("public_key", publicKey) - - privateKeySalt?.let { - put("private_key_salt", it) - } - privateKeyIterations?.let { - put("private_key_iterations", it) - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt index c668e78a9e8..0d708b8d735 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/MegolmBackupCreationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/MegolmBackupCreationInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.model +package org.matrix.android.sdk.api.session.crypto.keysbackup /** * Data retrieved from Olm library. algorithm and authData will be send to the homeserver, and recoveryKey will be displayed to the user diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKey.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt index 44774fd5a68..85d6ef43653 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/RecoveryKey.kt @@ -14,8 +14,10 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.keysbackup.util +package org.matrix.android.sdk.api.session.crypto.keysbackup +import org.matrix.android.sdk.internal.crypto.keysbackup.util.base58decode +import org.matrix.android.sdk.internal.crypto.keysbackup.util.base58encode import kotlin.experimental.xor /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/SavedKeyBackupKeyInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt similarity index 92% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/SavedKeyBackupKeyInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt index a48f4ecef5a..7f90fea9af0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/SavedKeyBackupKeyInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keysbackup/SavedKeyBackupKeyInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.store +package org.matrix.android.sdk.api.session.crypto.keysbackup data class SavedKeyBackupKeyInfo( val recoveryKey: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt index ba2d4ba3f69..3cd36c2ce8c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/keyshare/GossipingRequestListener.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.api.session.crypto.keyshare -import org.matrix.android.sdk.internal.crypto.IncomingRequestCancellation -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingRequestCancellation +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest /** * Room keys events listener diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoDeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoDeviceInfo.kt new file mode 100644 index 00000000000..418b1e6ce33 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/CryptoDeviceInfo.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.crypto.model + +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.internal.crypto.model.CryptoInfo + +data class CryptoDeviceInfo( + val deviceId: String, + override val userId: String, + val algorithms: List? = null, + override val keys: Map? = null, + override val signatures: Map>? = null, + val unsigned: UnsignedDeviceInfo? = null, + var trustLevel: DeviceTrustLevel? = null, + val isBlocked: Boolean = false, + val firstTimeSeenLocalTs: Long? = null +) : CryptoInfo { + + val isVerified: Boolean + get() = trustLevel?.isVerified() == true + + val isUnknown: Boolean + get() = trustLevel == null + + /** + * @return the fingerprint + */ + fun fingerprint(): String? { + return keys + ?.takeIf { deviceId.isNotBlank() } + ?.get("ed25519:$deviceId") + } + + /** + * @return the identity key + */ + fun identityKey(): String? { + return keys + ?.takeIf { deviceId.isNotBlank() } + ?.get("curve25519:$deviceId") + } + + /** + * @return the display name + */ + fun displayName(): String? { + return unsigned?.deviceDisplayName + } + + override fun signalableJSONDictionary(): Map { + val map = HashMap() + map["device_id"] = deviceId + map["user_id"] = userId + algorithms?.let { map["algorithms"] = it } + keys?.let { map["keys"] = it } + return map + } + + fun shortDebugString() = "$userId|$deviceId" +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt index c5cd4003427..221d0793d94 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DeviceInfo.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DevicesListResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DevicesListResponse.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DevicesListResponse.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DevicesListResponse.kt index eb325f332e2..01f33211661 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DevicesListResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/DevicesListResponse.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt index 4fc3adb42cc..13ad1df4765 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileInfo.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt index 71f266d7a51..859c6ac43f0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedFileKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/EncryptedFileKey.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ForwardedRoomKeyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ForwardedRoomKeyContent.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ForwardedRoomKeyContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ForwardedRoomKeyContent.kt index bbc24f04471..3df4ef7c9a0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ForwardedRoomKeyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ForwardedRoomKeyContent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingRequestState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt similarity index 76% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingRequestState.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt index e398cbfcaf2..d9a6f4fcba1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipingRequestState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingRequestState.kt @@ -14,12 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto - -enum class GossipRequestType { - KEY, - SECRET -} +package org.matrix.android.sdk.api.session.crypto.model enum class GossipingRequestState { NONE, @@ -34,13 +29,3 @@ enum class GossipingRequestState { CANCELLED_BY_REQUESTER, RE_REQUESTED } - -enum class OutgoingGossipingRequestState { - UNSENT, - SENDING, - SENT, - CANCELLING, - CANCELLED, - FAILED_TO_SEND, - FAILED_TO_CANCEL -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingToDeviceObject.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt similarity index 70% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingToDeviceObject.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt index e2ae9d1d6c4..1922b2bceef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingToDeviceObject.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/GossipingToDeviceObject.kt @@ -13,10 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass +package org.matrix.android.sdk.api.session.crypto.model /** * Interface representing an room key action request @@ -35,10 +33,3 @@ interface GossipingToDeviceObject : SendToDeviceObject { const val ACTION_SHARE_CANCELLATION = "request_cancellation" } } - -@JsonClass(generateAdapter = true) -data class GossipingDefaultContent( - @Json(name = "action") override val action: String?, - @Json(name = "requesting_device_id") override val requestingDeviceId: String?, - @Json(name = "m.request_id") override val requestId: String? = null -) : GossipingToDeviceObject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/ImportRoomKeysResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ImportRoomKeysResult.kt similarity index 76% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/ImportRoomKeysResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ImportRoomKeysResult.kt index e9d2a1bcd8b..b55f0e87479 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/ImportRoomKeysResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/ImportRoomKeysResult.kt @@ -14,7 +14,9 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model +package org.matrix.android.sdk.api.session.crypto.model -data class ImportRoomKeysResult(val totalNumberOfKeys: Int, - val successfullyNumberOfImportedKeys: Int) +data class ImportRoomKeysResult( + val totalNumberOfKeys: Int, + val successfullyNumberOfImportedKeys: Int +) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRequestCancellation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRequestCancellation.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt index 181bc0c1b1c..74ca7304f73 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRequestCancellation.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRequestCancellation.kt @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.session.crypto.model import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon import org.matrix.android.sdk.internal.crypto.model.rest.ShareRequestCancellation /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt similarity index 92% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRoomKeyRequest.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt index babc6008a2a..45b0926d891 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingRoomKeyRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingRoomKeyRequest.kt @@ -14,12 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.session.crypto.model import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest +import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon /** * IncomingRoomKeyRequest class defines the incoming room keys request. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingSecretShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingSecretShareRequest.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt index d2ee69196cb..5afffef1aed 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingSecretShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/IncomingSecretShareRequest.kt @@ -14,11 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.session.crypto.model import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest +import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon /** * IncomingSecretShareRequest class defines the incoming secret keys request. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXDeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXDeviceInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt index 68cc41005ef..286ab2b7d51 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXDeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXDeviceInfo.kt @@ -14,12 +14,11 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceKeys import java.io.Serializable @JsonClass(generateAdapter = true) @@ -144,19 +143,6 @@ data class MXDeviceInfo( return map } - /** - * @return a dictionary of the parameters - */ - fun toDeviceKeys(): DeviceKeys { - return DeviceKeys( - userId = userId, - deviceId = deviceId, - algorithms = algorithms!!, - keys = keys!!, - signatures = signatures!! - ) - } - override fun toString(): String { return "MXDeviceInfo $userId:$deviceId" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXEncryptEventContentResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXEncryptEventContentResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt index 524bc808432..706e40a769e 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXEncryptEventContentResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEncryptEventContentResult.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model +package org.matrix.android.sdk.api.session.crypto.model import org.matrix.android.sdk.api.session.events.model.Content diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXEventDecryptionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEventDecryptionResult.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXEventDecryptionResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEventDecryptionResult.kt index c66c37574ab..0a0ccc2db3e 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXEventDecryptionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXEventDecryptionResult.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.session.crypto.model import org.matrix.android.sdk.api.util.JsonDict @@ -22,7 +22,6 @@ import org.matrix.android.sdk.api.util.JsonDict * The result of a (successful) call to decryptEvent. */ data class MXEventDecryptionResult( - /** * The plaintext payload for the event (typically containing "type" and "content" fields). */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt new file mode 100755 index 00000000000..dc5567e908d --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/MXUsersDevicesMap.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2020 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.crypto.model + +class MXUsersDevicesMap { + + // A map of maps (userId -> (deviceId -> Object)). + val map = HashMap>() + + /** + * @return the user Ids + */ + val userIds: List + get() = map.keys.toList() + + val isEmpty: Boolean + get() = map.isEmpty() + + /** + * Provides the device ids list for a user id + * FIXME Should maybe return emptyList and not null, to avoid many !! in the code + * + * @param userId the user id + * @return the device ids list + */ + fun getUserDeviceIds(userId: String?): List? { + return if (!userId.isNullOrBlank() && map.containsKey(userId)) { + map[userId]!!.keys.toList() + } else null + } + + /** + * Provides the object for a device id and a user Id + * + * @param deviceId the device id + * @param userId the object id + * @return the object + */ + fun getObject(userId: String?, deviceId: String?): E? { + return if (!userId.isNullOrBlank() && !deviceId.isNullOrBlank()) { + map[userId]?.get(deviceId) + } else null + } + + /** + * Set an object for a dedicated user Id and device Id + * + * @param userId the user Id + * @param deviceId the device id + * @param o the object to set + */ + fun setObject(userId: String?, deviceId: String?, o: E?) { + if (null != o && userId?.isNotBlank() == true && deviceId?.isNotBlank() == true) { + val devices = map.getOrPut(userId) { HashMap() } + devices[deviceId] = o + } + } + + /** + * Defines the objects map for a user Id + * + * @param objectsPerDevices the objects maps + * @param userId the user id + */ + fun setObjects(userId: String?, objectsPerDevices: Map?) { + if (!userId.isNullOrBlank()) { + if (null == objectsPerDevices) { + map.remove(userId) + } else { + map[userId] = HashMap(objectsPerDevices) + } + } + } + + /** + * Removes objects for a dedicated user + * + * @param userId the user id. + */ + fun removeUserObjects(userId: String?) { + if (!userId.isNullOrBlank()) { + map.remove(userId) + } + } + + /** + * Clear the internal dictionary + */ + fun removeAllObjects() { + map.clear() + } + + /** + * Add entries from another MXUsersDevicesMap + * + * @param other the other one + */ + fun addEntriesFromMap(other: MXUsersDevicesMap?) { + if (null != other) { + map.putAll(other.map) + } + } + + override fun toString(): String { + return "MXUsersDevicesMap $map" + } +} + +inline fun MXUsersDevicesMap.forEach(action: (String, String, T) -> Unit) { + userIds.forEach { userId -> + getUserDeviceIds(userId)?.forEach { deviceId -> + getObject(userId, deviceId)?.let { + action(userId, deviceId, it) + } + } + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/OlmDecryptionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/OlmDecryptionResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt index 955f57afbaf..9cf2bf75fbd 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/OlmDecryptionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OlmDecryptionResult.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.algorithms.olm +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedBodyFileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt similarity index 63% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedBodyFileInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt index 90f97b65ebf..8c1bdf6768b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedBodyFileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingGossipingRequestState.kt @@ -13,17 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest -import org.matrix.olm.OlmPkMessage +package org.matrix.android.sdk.api.session.crypto.model -/** - * Build from a OlmPkMessage object - * - * @param olmPkMessage OlmPkMessage - */ -class EncryptedBodyFileInfo(olmPkMessage: OlmPkMessage) { - var ciphertext = olmPkMessage.mCipherText - var mac = olmPkMessage.mMac - var ephemeral = olmPkMessage.mEphemeralKey +enum class OutgoingGossipingRequestState { + UNSENT, + SENDING, + SENT, + CANCELLING, + CANCELLED, + FAILED_TO_SEND, + FAILED_TO_CANCEL } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingRoomKeyRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt similarity index 72% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingRoomKeyRequest.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt index 88025952db4..5f35cc908f9 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingRoomKeyRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/OutgoingRoomKeyRequest.kt @@ -14,10 +14,10 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody +import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequest /** * Represents an outgoing room key request @@ -25,14 +25,14 @@ import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody @JsonClass(generateAdapter = true) data class OutgoingRoomKeyRequest( // RequestBody - var requestBody: RoomKeyRequestBody?, + val requestBody: RoomKeyRequestBody?, // list of recipients for the request - override var recipients: Map>, + override val recipients: Map>, // Unique id for this request. Used for both // an id within the request for later pairing with a cancellation, and for // the transaction id when sending the to_device messages to our local - override var requestId: String, // current state of this request - override var state: OutgoingGossipingRequestState + override val requestId: String, // current state of this request + override val state: OutgoingGossipingRequestState // transaction id for the cancellation, if any // override var cancellationTxnId: String? = null ) : OutgoingGossipingRequest { @@ -43,9 +43,7 @@ data class OutgoingRoomKeyRequest( * @return the room id. */ val roomId: String? - get() = if (null != requestBody) { - requestBody!!.roomId - } else null + get() = requestBody?.roomId /** * Used only for log. @@ -53,7 +51,5 @@ data class OutgoingRoomKeyRequest( * @return the session id */ val sessionId: String? - get() = if (null != requestBody) { - requestBody!!.sessionId - } else null + get() = requestBody?.sessionId } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/RoomEncryptionTrustLevel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/RoomEncryptionTrustLevel.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt index 8ba99ad70b4..68c7496d58d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/RoomEncryptionTrustLevel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomEncryptionTrustLevel.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.crypto +package org.matrix.android.sdk.api.session.crypto.model /** * RoomEncryptionTrustLevel represents the trust level in an encrypted room. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyRequestBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyRequestBody.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt index 3eae2585a56..15163248dc9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyRequestBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyRequestBody.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyShareRequest.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt index 68fbf0b805e..b6bb4c55af9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RoomKeyShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/RoomKeyShareRequest.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SecretShareRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SecretShareRequest.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt index a4eeb50d8ba..60090778061 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SecretShareRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SecretShareRequest.kt @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest + +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceObject.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SendToDeviceObject.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceObject.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SendToDeviceObject.kt index b3a76b2a7c4..b866cb76cc8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/SendToDeviceObject.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/SendToDeviceObject.kt @@ -14,6 +14,6 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest +package org.matrix.android.sdk.api.session.crypto.model interface SendToDeviceObject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UnsignedDeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/UnsignedDeviceInfo.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UnsignedDeviceInfo.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/UnsignedDeviceInfo.kt index 5f316486b6e..1d9d1fce3e3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UnsignedDeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/model/UnsignedDeviceInfo.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest +package org.matrix.android.sdk.api.session.crypto.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/VerificationState.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationState.kt similarity index 87% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/VerificationState.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationState.kt index 54276a6b51e..fe855278a5e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/crypto/VerificationState.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/crypto/verification/VerificationState.kt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.api.crypto +package org.matrix.android.sdk.api.session.crypto.verification enum class VerificationState { REQUEST, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt index f1304f62163..1ce51a2bded 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt @@ -22,6 +22,8 @@ import org.json.JSONObject import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent @@ -34,8 +36,7 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.threads.ThreadDetails import org.matrix.android.sdk.api.util.ContentUtils import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent +import org.matrix.android.sdk.api.util.MatrixJsonParser import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.session.presence.model.PresenceContent import timber.log.Timber @@ -46,7 +47,7 @@ typealias Content = JsonDict * This methods is a facility method to map a json content to a model. */ inline fun Content?.toModel(catchError: Boolean = true): T? { - val moshi = MoshiProvider.providesMoshi() + val moshi = MatrixJsonParser.getMoshi() val moshiAdapter = moshi.adapter(T::class.java) return try { moshiAdapter.fromJsonValue(this) @@ -65,7 +66,7 @@ inline fun Content?.toModel(catchError: Boolean = true): T? { */ @Suppress("UNCHECKED_CAST") inline fun T.toContent(): Content { - val moshi = MoshiProvider.providesMoshi() + val moshi = MatrixJsonParser.getMoshi() val moshiAdapter = moshi.adapter(T::class.java) return moshiAdapter.toJsonValue(this) as Content } @@ -202,7 +203,9 @@ data class Event( fun getDecryptedTextSummary(): String? { if (isRedacted()) return "Message Deleted" val text = getDecryptedValue() ?: run { - if (isPoll()) { return getPollQuestion() ?: "created a poll." } + if (isPoll()) { + return getPollQuestion() ?: "created a poll." + } return null } @@ -300,57 +303,67 @@ data class Event( } } +/** + * Return the value of "content.msgtype", if the Event type is "m.room.message" + * and if the content has it, and if it is a String + */ +fun Event.getMsgType(): String? { + if (getClearType() != EventType.MESSAGE) return null + return getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY) as? String +} + fun Event.isTextMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_TEXT, - MessageType.MSGTYPE_EMOTE, - MessageType.MSGTYPE_NOTICE -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_TEXT, + MessageType.MSGTYPE_EMOTE, + MessageType.MSGTYPE_NOTICE -> true + else -> false + } } fun Event.isImageMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_IMAGE -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_IMAGE -> true + else -> false + } } fun Event.isVideoMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_VIDEO -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_VIDEO -> true + else -> false + } } fun Event.isAudioMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_AUDIO -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_AUDIO -> true + else -> false + } } fun Event.isFileMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_FILE -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_FILE -> true + else -> false + } } fun Event.isAttachmentMessage(): Boolean { - return getClearType() == EventType.MESSAGE && - when (getClearContent()?.get(MessageContent.MSG_TYPE_JSON_KEY)) { - MessageType.MSGTYPE_IMAGE, - MessageType.MSGTYPE_AUDIO, - MessageType.MSGTYPE_VIDEO, - MessageType.MSGTYPE_FILE -> true - else -> false - } + return when (getMsgType()) { + MessageType.MSGTYPE_IMAGE, + MessageType.MSGTYPE_AUDIO, + MessageType.MSGTYPE_VIDEO, + MessageType.MSGTYPE_FILE -> true + else -> false + } +} + +fun Event.isLocationMessage(): Boolean { + return when (getMsgType()) { + MessageType.MSGTYPE_LOCATION -> true + else -> false + } } fun Event.isPoll(): Boolean = getClearType() in EventType.POLL_START || getClearType() in EventType.POLL_END @@ -400,7 +413,7 @@ fun Event.isEdition(): Boolean { return getRelationContentForType(RelationType.REPLACE)?.eventId != null } -fun Event.getPresenceContent(): PresenceContent? { +internal fun Event.getPresenceContent(): PresenceContent? { return content.toModel() } @@ -411,4 +424,5 @@ fun Event.getPollContent(): MessagePollContent? { return content.toModel() } -fun Event.supportsNotification() = this.getClearType() in EventType.MESSAGE + EventType.POLL_START +fun Event.supportsNotification() = + this.getClearType() in EventType.MESSAGE + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt index 855801e79ec..fa3a9f6acd6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/EventType.kt @@ -49,7 +49,8 @@ object EventType { const val STATE_ROOM_JOIN_RULES = "m.room.join_rules" const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access" const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels" - private const val STATE_ROOM_BEACON_INFO_PREFIX = "org.matrix.msc3489.beacon_info." + val STATE_ROOM_BEACON_INFO = listOf("org.matrix.msc3672.beacon_info", "m.beacon_info") + val BEACON_LOCATION_DATA = listOf("org.matrix.msc3672.beacon", "m.beacon") const val STATE_SPACE_CHILD = "m.space.child" @@ -121,12 +122,4 @@ object EventType { type == CALL_REJECT || type == CALL_REPLACES } - - /** - * Returns an event type like org.matrix.msc3489.beacon_info.@userid:matrix.org.1648814272273 - */ - fun generateBeaconInfoStateEventType(userId: String): String { - val uniqueId = System.currentTimeMillis() - return "$STATE_ROOM_BEACON_INFO_PREFIX$userId.$uniqueId" - } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptedEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptedEventContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt index 93a6377bbbe..4f39bb61e14 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptedEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptedEventContent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptionEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptionEventContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt index dd76ae1d8e1..103293ba831 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/EncryptionEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/EncryptionEventContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmEventContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt index 6fd06270226..b972dd20bbf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmEventContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt index 3ce9d36f908..6060ab5c4b2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/OlmPayloadContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/OlmPayloadContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt similarity index 90% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt index 7fa0e837254..43a47b818f6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyContent.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyWithHeldContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt similarity index 98% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyWithHeldContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt index 4c462357dbf..a577daf9e42 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/RoomKeyWithHeldContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/RoomKeyWithHeldContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/SecretSendEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/SecretSendEventContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt index 4dcca04e942..5099aba4030 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/SecretSendEventContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/content/SecretSendEventContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event +package org.matrix.android.sdk.api.session.events.model.content import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt index f76e4be4401..72f8019ada3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/file/FileService.kt @@ -17,11 +17,11 @@ package org.matrix.android.sdk.api.session.file import android.net.Uri +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt +import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent import org.matrix.android.sdk.api.session.room.model.message.getFileName import org.matrix.android.sdk.api.session.room.model.message.getFileUrl -import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt -import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt import java.io.File /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt index 9db3876b747..597c1a0ca8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/homeserver/HomeServerCapabilities.kt @@ -54,7 +54,7 @@ data class HomeServerCapabilities( /** * True if the home server support threading */ - var canUseThreading: Boolean = false + val canUseThreading: Boolean = false ) { enum class RoomCapabilitySupport { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt index a22cd572fa4..fdcb30a5c82 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/IdentityService.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.identity -import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult +import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult /** * Provides access to the identity server configuration and services identity server can provide diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt similarity index 64% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt index 27a3f3209f2..b1662b9cf82 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/model/SignInvitationResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/identity/model/SignInvitationResult.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,18 +14,26 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.identity.model +package org.matrix.android.sdk.api.session.identity.model import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) data class SignInvitationResult( - /** The Matrix user ID of the user accepting the invitation.*/ + /** + * The Matrix user ID of the user accepting the invitation. + */ val mxid: String, - /** The Matrix user ID of the user who sent the invitation.*/ + /** + * The Matrix user ID of the user who sent the invitation. + */ val sender: String, - /**The token from the call to store- invite..*/ + /** + * The token from the call to store- invite.. + */ val signatures: Map, - /** The token for the invitation */ + /** + * The token for the invitation + */ val token: String ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt index daab6d97611..267436916ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/initsync/SyncStatusService.kt @@ -28,7 +28,7 @@ interface SyncStatusService { abstract class InitialSyncStatus : Status() object Idle : InitialSyncStatus() - data class Progressing( + data class InitialSyncProgressing( val initSyncStep: InitSyncStep, val percentProgress: Int = 0 ) : InitialSyncStatus() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt index c1c1a385b5c..700e292b0c1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/RoomService.kt @@ -19,6 +19,8 @@ package org.matrix.android.sdk.api.session.room import androidx.lifecycle.LiveData import androidx.paging.PagedList import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult +import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary @@ -27,8 +29,6 @@ import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams import org.matrix.android.sdk.api.session.room.peeking.PeekResult import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult -import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription /** * This interface defines methods to get rooms. It's implemented at the session level. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasDescription.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/RoomAliasDescription.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasDescription.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/RoomAliasDescription.kt index d1f93c50bef..ce7b03d35b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/RoomAliasDescription.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/alias/RoomAliasDescription.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.room.alias +package org.matrix.android.sdk.api.session.room.alias import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/crypto/RoomCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/crypto/RoomCryptoService.kt index 445d16b72bc..6967e0c4550 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/crypto/RoomCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/crypto/RoomCryptoService.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.room.crypto -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM interface RoomCryptoService { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt index 3a4912e457c..0238eb6c8de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/EventAnnotationsSummary.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.api.session.room.model data class EventAnnotationsSummary( - var eventId: String, - var reactionsSummary: List = emptyList(), - var editSummary: EditAggregatedSummary? = null, - var pollResponseSummary: PollResponseAggregatedSummary? = null, - var referencesAggregatedSummary: ReferencesAggregatedSummary? = null + val eventId: String, + val reactionsSummary: List = emptyList(), + val editSummary: EditAggregatedSummary? = null, + val pollResponseSummary: PollResponseAggregatedSummary? = null, + val referencesAggregatedSummary: ReferencesAggregatedSummary? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollResponseAggregatedSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollResponseAggregatedSummary.kt index a15d8be0849..b16852e47d1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollResponseAggregatedSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollResponseAggregatedSummary.kt @@ -16,13 +16,11 @@ package org.matrix.android.sdk.api.session.room.model data class PollResponseAggregatedSummary( - - var aggregatedContent: PollSummaryContent? = null, - + val aggregatedContent: PollSummaryContent? = null, // If set the poll is closed (Clients SHOULD NOT consider responses after the close event) - var closedTime: Long? = null, + val closedTime: Long? = null, // Clients SHOULD validate that the option in the relationship is a valid option, and ignore the response if invalid - var nbOptions: Int = 0, + val nbOptions: Int = 0, // The list of the eventIDs used to build the summary (might be out of sync if chunked received from message chunk) val sourceEvents: List, val localEchos: List diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollSummaryContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollSummaryContent.kt index f1e4354314d..09458ff12ea 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollSummaryContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/PollSummaryContent.kt @@ -24,13 +24,13 @@ import com.squareup.moshi.JsonClass */ @JsonClass(generateAdapter = true) data class PollSummaryContent( - var myVote: String? = null, - // Array of VoteInfo, list is constructed so that there is only one vote by user + val myVote: String? = null, + // List of VoteInfo, list is constructed so that there is only one vote by user // And that optionIndex is valid - var votes: List? = null, - var votesSummary: Map? = null, - var totalVotes: Int = 0, - var winnerVoteCount: Int = 0 + val votes: List? = null, + val votesSummary: Map? = null, + val totalVotes: Int = 0, + val winnerVoteCount: Int = 0 ) @JsonClass(generateAdapter = true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedContent.kt index 664d042e186..c6b94c5dd15 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/ReferencesAggregatedContent.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.api.session.room.model import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.api.crypto.VerificationState +import org.matrix.android.sdk.api.session.crypto.verification.VerificationState /** * Contains an aggregated summary info of the references. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomEncryptionAlgorithm.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomEncryptionAlgorithm.kt index f6812169294..5f728a4ed44 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomEncryptionAlgorithm.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomEncryptionAlgorithm.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.room.model -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM sealed class RoomEncryptionAlgorithm { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt index c793a04f9de..71c1d8303e5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/RoomSummary.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.room.model -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.presence.model.UserPresence import org.matrix.android.sdk.api.session.room.model.tag.RoomTag import org.matrix.android.sdk.api.session.room.send.UserDraft diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt index 56679060003..ce1e0e0d144 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/create/CreateRoomParams.kt @@ -17,12 +17,12 @@ package org.matrix.android.sdk.api.session.room.model.create import android.net.Uri +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.room.model.GuestAccess import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM open class CreateRoomParams { /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt index e08d5b629b5..106e76eafd0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/livelocation/LiveLocationBeaconContent.kt @@ -18,15 +18,30 @@ package org.matrix.android.sdk.api.session.room.model.livelocation import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.message.LocationAsset import org.matrix.android.sdk.api.session.room.model.message.LocationAssetType +import org.matrix.android.sdk.api.session.room.model.message.MessageContent +import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent +import org.matrix.android.sdk.api.session.room.model.message.MessageType +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent @JsonClass(generateAdapter = true) data class LiveLocationBeaconContent( + /** + * Local message type, not from server + */ + @Transient + override val msgType: String = MessageType.MSGTYPE_LIVE_LOCATION_STATE, + + @Json(name = "body") override val body: String = "", + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, + @Json(name = "m.new_content") override val newContent: Content? = null, + /** * Indicates user's intent to share ephemeral location. */ - @Json(name = "org.matrix.msc3489.beacon_info") val unstableBeaconInfo: BeaconInfo? = null, + @Json(name = "org.matrix.msc3672.beacon_info") val unstableBeaconInfo: BeaconInfo? = null, @Json(name = "m.beacon_info") val beaconInfo: BeaconInfo? = null, /** * Beacon creation timestamp. @@ -37,8 +52,18 @@ data class LiveLocationBeaconContent( * Live location asset type. */ @Json(name = "org.matrix.msc3488.asset") val unstableLocationAsset: LocationAsset = LocationAsset(LocationAssetType.SELF), - @Json(name = "m.asset") val locationAsset: LocationAsset? = null -) { + @Json(name = "m.asset") val locationAsset: LocationAsset? = null, + + /** + * Client side tracking of the last location + */ + var lastLocationContent: MessageLiveLocationContent? = null, + + /** + * Client side tracking of whether the beacon has timed out. + */ + var hasTimedOut: Boolean = false +) : MessageContent { fun getBestBeaconInfo() = beaconInfo ?: unstableBeaconInfo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt index f21074096ef..fa18bfd21f7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/FileInfo.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo @JsonClass(generateAdapter = true) data class FileInfo( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt index c38ef5bc276..0099208320e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/ImageInfo.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo @JsonClass(generateAdapter = true) data class ImageInfo( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt index ebf3d127ce4..76a612b51ba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageAudioContent.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class MessageAudioContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt index 78f9a5d2f2d..b5303e6c5d7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageFileContent.kt @@ -19,9 +19,9 @@ package org.matrix.android.sdk.api.session.room.model.message import android.webkit.MimeTypeMap import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class MessageFileContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt index ea7ab506887..f0caf52041c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageImageContent.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class MessageImageContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt new file mode 100644 index 00000000000..548dc853694 --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageLiveLocationContent.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.session.room.model.message + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.events.model.Content +import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent + +@JsonClass(generateAdapter = true) +data class MessageLiveLocationContent( + /** + * Local message type, not from server + */ + @Transient + override val msgType: String = MessageType.MSGTYPE_LIVE_LOCATION, + + @Json(name = "body") override val body: String = "", + @Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null, + @Json(name = "m.new_content") override val newContent: Content? = null, + + /** + * See [MSC3488](https://github.com/matrix-org/matrix-doc/blob/matthew/location/proposals/3488-location.md) + */ + @Json(name = "org.matrix.msc3488.location") val unstableLocationInfo: LocationInfo? = null, + @Json(name = "m.location") val locationInfo: LocationInfo? = null, + + /** + * Exact time that the data in the event refers to (milliseconds since the UNIX epoch) + */ + @Json(name = "org.matrix.msc3488.ts") val unstableTimestampAsMilliseconds: Long? = null, + @Json(name = "m.ts") val timestampAsMilliseconds: Long? = null +) : MessageContent { + + fun getBestLocationInfo() = locationInfo ?: unstableLocationInfo + + fun getBestTimestampAsMilliseconds() = timestampAsMilliseconds ?: unstableTimestampAsMilliseconds +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt index 8e1d4d3d758..3d774cadb29 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageStickerContent.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class MessageStickerContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt index 2a6138ae60c..106bf2e0308 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageType.kt @@ -33,10 +33,14 @@ object MessageType { const val MSGTYPE_STICKER_LOCAL = "org.matrix.android.sdk.sticker" // Fake message types for poll events to be able to inherit them from MessageContent - // Because poll events are not message events and they don't hanve msgtype field + // Because poll events are not message events and they don't have msgtype field const val MSGTYPE_POLL_START = "org.matrix.android.sdk.poll.start" const val MSGTYPE_POLL_RESPONSE = "org.matrix.android.sdk.poll.response" const val MSGTYPE_CONFETTI = "nic.custom.confetti" const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall" + + // Fake message types for live location events to be able to inherit them from MessageContent + const val MSGTYPE_LIVE_LOCATION_STATE = "org.matrix.android.sdk.livelocation.state" + const val MSGTYPE_LIVE_LOCATION = "org.matrix.android.sdk.livelocation" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt index e1b0cd86074..9266a0fb0f3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageVideoContent.kt @@ -18,9 +18,9 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo @JsonClass(generateAdapter = true) data class MessageVideoContent( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt index 7870db4f65a..95dfb6b8648 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageWithAttachmentContent.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.api.session.room.model.message -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo /** * Interface for message which can contains an encrypted file diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt index 8a36c26313d..28f3a47d114 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/VideoInfo.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo @JsonClass(generateAdapter = true) data class VideoInfo( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt index 9f8b1d93d71..af7ab11df13 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/send/SendService.kt @@ -146,6 +146,15 @@ interface SendService { */ fun sendLocation(latitude: Double, longitude: Double, uncertainty: Double?, isUserLocation: Boolean): Cancelable + /** + * Send a live location event to the room. beacon_info state event has to be sent before sending live location updates. + * @param beaconInfoEventId event id of the initial beacon info state event + * @param latitude required latitude of the location + * @param longitude required longitude of the location + * @param uncertainty Accuracy of the location in meters + */ + fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable + /** * Remove this failed message from the timeline * @param localEcho the unsent local echo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt index e9b0e4f6760..f645f3ebf9c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/state/StateService.kt @@ -66,6 +66,19 @@ interface StateService { */ suspend fun deleteAvatar() + /** + * Stops sharing live location in the room + * @param userId user id + */ + suspend fun stopLiveLocation(userId: String) + + /** + * Returns beacon info state event of a user + * @param userId user id who is sharing location + * @param filterOnlyLive filters only ongoing live location sharing beacons if true else ended event is included + */ + suspend fun getLiveLocationBeaconInfo(userId: String, filterOnlyLive: Boolean): Event? + /** * Send a state event to the room * @param eventType The type of event to send. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomSummaryConstants.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomSummaryConstants.kt index eaed9053eae..8f214e0f894 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomSummaryConstants.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomSummaryConstants.kt @@ -33,5 +33,5 @@ object RoomSummaryConstants { EventType.ENCRYPTED, EventType.STICKER, EventType.REACTION - ) + EventType.POLL_START + ) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/taggedevents/TaggedEventsContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/taggedevents/TaggedEventsContent.kt similarity index 97% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/taggedevents/TaggedEventsContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/taggedevents/TaggedEventsContent.kt index 1b19d27e1d4..521a2315e47 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/taggedevents/TaggedEventsContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/taggedevents/TaggedEventsContent.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.room.taggedevents +package org.matrix.android.sdk.api.session.room.taggedevents import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt index 1b01efc074b..a2ae8bfeb52 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/TimelineEvent.kt @@ -29,6 +29,7 @@ import org.matrix.android.sdk.api.session.events.model.isSticker import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary import org.matrix.android.sdk.api.session.room.model.ReadReceipt +import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent @@ -55,7 +56,7 @@ data class TimelineEvent( * It's not unique on the timeline as it's reset on each chunk. */ val displayIndex: Int, - var ownedByThreadChunk: Boolean = false, + val ownedByThreadChunk: Boolean = false, val senderInfo: SenderInfo, val annotations: EventAnnotationsSummary? = null, val readReceipts: List = emptyList() @@ -136,9 +137,10 @@ fun TimelineEvent.getEditedEventId(): String? { */ fun TimelineEvent.getLastMessageContent(): MessageContent? { return when (root.getClearType()) { - EventType.STICKER -> root.getClearContent().toModel() - in EventType.POLL_START -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() - else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() + EventType.STICKER -> root.getClearContent().toModel() + in EventType.POLL_START -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() + in EventType.STATE_ROOM_BEACON_INFO -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() + else -> (annotations?.editSummary?.latestContent ?: root.getClearContent()).toModel() } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeyCreationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeyCreationInfo.kt index eeb1b31f9cc..7a91a16c8c0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeyCreationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeyCreationInfo.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.api.session.securestorage data class SsssKeyCreationInfo( val keyId: String = "", - var content: SecretStorageKeyContent?, + val content: SecretStorageKeyContent?, val recoveryKey: String = "", val keySpec: SsssKeySpec ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt index f791ea4e86f..03efb9b3dbb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/securestorage/SsssKeySpec.kt @@ -17,8 +17,8 @@ package org.matrix.android.sdk.api.session.securestorage import org.matrix.android.sdk.api.listeners.ProgressListener +import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.internal.crypto.keysbackup.deriveKey -import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey /** Tag class */ interface SsssKeySpec diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt index 41c4e7eed18..f4460b76599 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/SpaceService.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams import org.matrix.android.sdk.api.session.room.model.RoomSummary -import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult +import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult typealias SpaceSummaryQueryParams = RoomSummaryQueryParams diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/SpacePeekResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/peeking/SpacePeekResult.kt similarity index 88% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/SpacePeekResult.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/peeking/SpacePeekResult.kt index a2ffd8221ac..06dbd12d7a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/SpacePeekResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/space/peeking/SpacePeekResult.kt @@ -14,11 +14,18 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.space.peeking +package org.matrix.android.sdk.api.session.space.peeking import org.matrix.android.sdk.api.session.room.peeking.PeekResult -// TODO Move to api package +sealed class SpacePeekResult { + abstract class SpacePeekError : SpacePeekResult() + data class FailedToResolve(val spaceId: String, val roomPeekResult: PeekResult) : SpacePeekError() + data class NotSpaceType(val spaceId: String) : SpacePeekError() + + data class Success(val summary: SpacePeekSummary) : SpacePeekResult() +} + data class SpacePeekSummary( val idOrAlias: String, val roomPeekResult: PeekResult.Success, @@ -28,30 +35,18 @@ data class SpacePeekSummary( interface ISpaceChild { val id: String val roomPeekResult: PeekResult - -// val default: Boolean? val order: String? } data class SpaceChildPeekResult( override val id: String, override val roomPeekResult: PeekResult, -// override val default: Boolean? = null, override val order: String? = null ) : ISpaceChild data class SpaceSubChildPeekResult( override val id: String, override val roomPeekResult: PeekResult, -// override val default: Boolean?, override val order: String?, val children: List ) : ISpaceChild - -sealed class SpacePeekResult { - abstract class SpacePeekError : SpacePeekResult() - data class FailedToResolve(val spaceId: String, val roomPeekResult: PeekResult) : SpacePeekError() - data class NotSpaceType(val spaceId: String) : SpacePeekError() - - data class Success(val summary: SpacePeekSummary) : SpacePeekResult() -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStrategy.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt index 4bc866b36d4..461d816ea7c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/InitialSyncStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/InitialSyncStrategy.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.sync +package org.matrix.android.sdk.api.session.sync var initialSyncStrategy: InitialSyncStrategy = InitialSyncStrategy.Optimized() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt similarity index 98% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt index 97ae9b3a689..ac81be2174b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/sync/job/SyncService.kt @@ -1,11 +1,11 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.session.sync.job + +package org.matrix.android.sdk.api.session.sync.job import android.app.Service import android.content.Intent diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/GetTermsResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/GetTermsResponse.kt index e6d33cade68..b7bdc2b770c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/GetTermsResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/GetTermsResponse.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.api.session.terms -import org.matrix.android.sdk.internal.session.terms.TermsResponse - data class GetTermsResponse( val serverResponse: TermsResponse, val alreadyAcceptedTermUrls: Set diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt similarity index 93% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsResponse.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt index a185e0b80f3..9a30b4d764d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsResponse.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsResponse.kt @@ -14,12 +14,12 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.session.terms +package org.matrix.android.sdk.api.session.terms import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms /** * This class represent a localized privacy policy for registration Flow. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt index e64cf1872ee..6c357b2224d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/terms/TermsService.kt @@ -16,8 +16,6 @@ package org.matrix.android.sdk.api.session.terms -import org.matrix.android.sdk.internal.session.terms.TermsResponse - interface TermsService { enum class ServiceType { IntegrationManager, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadDetails.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadDetails.kt index d6937d5b265..c8fe1c85ea1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadDetails.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/threads/ThreadDetails.kt @@ -29,7 +29,7 @@ data class ThreadDetails( val threadSummarySenderInfo: SenderInfo? = null, val threadSummaryLatestEvent: Event? = null, val lastMessageTimestamp: Long? = null, - var threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE, + val threadNotificationState: ThreadNotificationState = ThreadNotificationState.NO_NEW_MESSAGE, val isThread: Boolean = false, val lastRootThreadEdition: String? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DefaultBaseAuth.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/DefaultBaseAuth.kt similarity index 91% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DefaultBaseAuth.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/DefaultBaseAuth.kt index bbb4a3a6548..865e02daf28 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DefaultBaseAuth.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/DefaultBaseAuth.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest +package org.matrix.android.sdk.api.session.uia import org.matrix.android.sdk.api.auth.UIABaseAuth diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/InteractiveAuthenticationFlow.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/InteractiveAuthenticationFlow.kt similarity index 94% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/InteractiveAuthenticationFlow.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/InteractiveAuthenticationFlow.kt index d66bcfb2740..a78c047221c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/data/InteractiveAuthenticationFlow.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/uia/InteractiveAuthenticationFlow.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.auth.data +package org.matrix.android.sdk.api.session.uia import com.squareup.moshi.Json import com.squareup.moshi.JsonClass diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt index cd4fb216d32..063abdb5a0d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/UserService.kt @@ -75,11 +75,14 @@ interface UserService { /** * Ignore users + * Note: once done, for the change to take effect, you have to request an initial sync. + * This may be improved in the future */ suspend fun ignoreUserIds(userIds: List) /** * Un-ignore some users + * Note: once done, for the change to take effect, you have to request an initial sync. */ suspend fun unIgnoreUserIds(userIds: List) } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt index 54ae9e54f6a..79c86f3f231 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/user/model/User.kt @@ -16,6 +16,9 @@ package org.matrix.android.sdk.api.session.user.model +import org.matrix.android.sdk.api.session.profile.ProfileService +import org.matrix.android.sdk.api.util.JsonDict + /** * Data class which holds information about a user. * It can be retrieved with [org.matrix.android.sdk.api.session.user.UserService] @@ -27,4 +30,14 @@ data class User( */ val displayName: String? = null, val avatarUrl: String? = null -) +) { + + companion object { + + fun fromJson(userId: String, json: JsonDict) = User( + userId = userId, + displayName = json[ProfileService.DISPLAY_NAME_KEY] as? String, + avatarUrl = json[ProfileService.AVATAR_URL_KEY] as? String + ) + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/settings/LightweightSettingsStorage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/settings/LightweightSettingsStorage.kt new file mode 100644 index 00000000000..8dd20a702be --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/settings/LightweightSettingsStorage.kt @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.settings + +interface LightweightSettingsStorage { + fun setThreadMessagesEnabled(enabled: Boolean) + fun areThreadMessagesEnabled(): Boolean +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Base64.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Base64.kt new file mode 100644 index 00000000000..e0596c1325c --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Base64.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.util + +import android.util.Base64 + +fun ByteArray.toBase64NoPadding(): String { + return Base64.encodeToString(this, Base64.NO_PADDING or Base64.NO_WRAP) +} + +fun String.fromBase64(): ByteArray { + return Base64.decode(this, Base64.DEFAULT) +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Hash.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt similarity index 95% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Hash.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt index 47f20913eca..7465eed3aeb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Hash.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/Hash.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.matrix.android.sdk.internal.util +package org.matrix.android.sdk.api.util import java.security.MessageDigest import java.util.Locale diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt index 650b8cc26db..4f5f4f82d93 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixItem.kt @@ -37,6 +37,7 @@ sealed class MatrixItem( override val displayName: String? = null, override val avatarUrl: String? = null) : MatrixItem(id, displayName?.removeSuffix(IRC_PATTERN), avatarUrl) { + init { if (BuildConfig.DEBUG) checkId() } @@ -200,7 +201,7 @@ fun RoomMemberSummary.toMatrixItem() = MatrixItem.UserItem(userId, displayName, fun SenderInfo.toMatrixItem() = MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) -fun SenderInfo.toMatrixItemOrNull() = tryOrNull { MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) } +fun SenderInfo.toMatrixItemOrNull() = tryOrNull { MatrixItem.UserItem(userId, disambiguatedDisplayName, avatarUrl) } fun SpaceChildInfo.toMatrixItem() = if (roomType == RoomType.SPACE) { MatrixItem.SpaceItem(childRoomId, name ?: canonicalAlias, avatarUrl) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt new file mode 100644 index 00000000000..48a41667b2c --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/MatrixJsonParser.kt @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.util + +import com.squareup.moshi.Moshi +import org.matrix.android.sdk.internal.di.MoshiProvider + +/** + * Entry point to get a Json parser + */ +object MatrixJsonParser { + /** + * @return a Moshi Json parser instance, configured to handle some Matrix Event contents + */ + fun getMoshi(): Moshi { + return MoshiProvider.providesMoshi() + } +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SuspendMatrixCallback.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/SuspendMatrixCallback.kt similarity index 96% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SuspendMatrixCallback.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/SuspendMatrixCallback.kt index 145fc92feac..381dfb65fae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/SuspendMatrixCallback.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/SuspendMatrixCallback.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.util +package org.matrix.android.sdk.api.util import org.matrix.android.sdk.api.MatrixCallback import kotlin.coroutines.resume diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt new file mode 100644 index 00000000000..fe12d7b1cfd --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/util/TextContent.kt @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.android.sdk.api.util + +/** + * Contains a text and eventually a formatted text + */ +data class TextContent( + val text: String, + val formattedText: String? = null +) { + fun takeFormatted() = formattedText ?: text +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultHomeServerHistoryService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultHomeServerHistoryService.kt index 7415938ebc2..c57ce6875d2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultHomeServerHistoryService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/DefaultHomeServerHistoryService.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.database.model.KnownServerUrlEntity import org.matrix.android.sdk.internal.di.GlobalDatabase import javax.inject.Inject -class DefaultHomeServerHistoryService @Inject constructor( +internal class DefaultHomeServerHistoryService @Inject constructor( @GlobalDatabase private val monarchy: Monarchy ) : HomeServerHistoryService { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo001.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo001.kt index 627f4e16bc5..a8d5e296897 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo001.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo001.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.auth.db.PendingSessionEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateAuthTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) { +internal class MigrateAuthTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Create PendingSessionEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo002.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo002.kt index 6b133f8580d..ef3a3e7f9bb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo002.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo002.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.auth.db.SessionParamsEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateAuthTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) { +internal class MigrateAuthTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Add boolean isTokenValid in SessionParamsEntity, with value true") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo003.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo003.kt index 9319ec99871..2584df18959 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo003.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo003.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateAuthTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) { +internal class MigrateAuthTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Update SessionParamsEntity primary key, to allow several sessions with the same userId") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo004.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo004.kt index 4a9b9022d58..6dfec6a1aae 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo004.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/db/migration/MigrateAuthTo004.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateAuthTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { +internal class MigrateAuthTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Update SessionParamsEntity to add HomeServerConnectionConfig.homeServerUriBase value") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt index 23fdbc613a1..cb17207741b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/AuthParams.kt @@ -88,15 +88,3 @@ internal data class AuthParams( } } } - -@JsonClass(generateAdapter = true) -data class ThreePidCredentials( - @Json(name = "client_secret") - val clientSecret: String? = null, - - @Json(name = "id_server") - val idServer: String? = null, - - @Json(name = "sid") - val sid: String? = null -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/SuccessResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/SuccessResult.kt index 9b158cce90a..c666eec749b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/SuccessResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/SuccessResult.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.extensions.orFalse @JsonClass(generateAdapter = true) -data class SuccessResult( +internal data class SuccessResult( @Json(name = "success") val success: Boolean? ) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/NewDeviceContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidCredentials.kt similarity index 64% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/NewDeviceContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidCredentials.kt index 2a63b4bee81..296ccadf916 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/event/NewDeviceContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ThreePidCredentials.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Matrix.org Foundation C.I.C. + * Copyright (c) 2022 The Matrix.org Foundation C.I.C. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,18 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.event + +package org.matrix.android.sdk.internal.auth.registration import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class NewDeviceContent( - // the device id - @Json(name = "device_id") - val deviceId: String? = null, +internal data class ThreePidCredentials( + @Json(name = "client_secret") + val clientSecret: String? = null, + + @Json(name = "id_server") + val idServer: String? = null, - // the room ids list - @Json(name = "rooms") - val rooms: List? = null + @Json(name = "sid") + val sid: String? = null ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt index b6f3e839299..ae71ae3a08a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/auth/registration/ValidationCodeBody.kt @@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass * This object is used to send a code received by SMS to validate Msisdn ownership */ @JsonClass(generateAdapter = true) -data class ValidationCodeBody( +internal data class ValidationCodeBody( @Json(name = "client_secret") val clientSecret: String, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt index 3a5f8e7668f..98950374edd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/CancelGossipRequestWorker.kt @@ -21,11 +21,12 @@ import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.ShareRequestCancellation import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt index db44abc36ff..6a57d94677d 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DefaultCryptoService.kt @@ -32,6 +32,8 @@ import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.NoOpMatrixCallback import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_OLM import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.failure.Failure @@ -39,14 +41,31 @@ import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility @@ -61,21 +80,8 @@ import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmEncryptionFactory import org.matrix.android.sdk.internal.crypto.algorithms.olm.MXOlmEncryptionFactory import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXEncryptEventContentResult import org.matrix.android.sdk.internal.crypto.model.MXKey.Companion.KEY_SIGNED_CURVE_25519_TYPE -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.model.toRest import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt index 494e6d7cc7a..6cae2d09358 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/DeviceListManager.kt @@ -21,10 +21,10 @@ import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.CryptoInfoMapper -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.DownloadKeysForUsersTask import org.matrix.android.sdk.internal.session.SessionScope diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt index 00efd3d6a85..1c8bce7377c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/EventDecryptor.kt @@ -21,15 +21,17 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_OLM import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.extensions.foldToCallback diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DummyContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipRequestType.kt similarity index 75% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DummyContent.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipRequestType.kt index 53d6e4a80a2..266c1a27442 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DummyContent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/GossipRequestType.kt @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.matrix.android.sdk.internal.crypto.model.rest -/** - * Class representing the dummy content - * Ref: https://matrix.org/docs/spec/client_server/latest#id82 - */ -typealias DummyContent = Unit +package org.matrix.android.sdk.internal.crypto + +internal enum class GossipRequestType { + KEY, + SECRET +} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt index 34bef61c986..a78444dff9f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/InboundGroupSessionStore.kt @@ -30,7 +30,7 @@ import java.util.Timer import java.util.TimerTask import javax.inject.Inject -data class InboundGroupSessionHolder( +internal data class InboundGroupSessionHolder( val wrapper: OlmInboundGroupSessionWrapper2, val mutex: Mutex = Mutex() ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt index 220f25ec800..3a409cf3fdb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingGossipingRequestManager.kt @@ -20,21 +20,26 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.IncomingRequestCancellation +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel +import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption -import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding -import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey import org.matrix.android.sdk.internal.crypto.model.rest.GossipingDefaultContent -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.di.SessionId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt index 86e9610148b..97c369db3ec 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/IncomingShareRequestCommon.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto -interface IncomingShareRequestCommon { +internal interface IncomingShareRequestCommon { /** * The user id */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt index 07881c7d797..5a5ee9e6968 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXCryptoAlgorithms.kt @@ -16,6 +16,9 @@ package org.matrix.android.sdk.internal.crypto +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_OLM + // TODO Update comment internal object MXCryptoAlgorithms { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt index e5ffa0ed7d2..f8235bf344f 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXMegolmExportEncryption.kt @@ -33,7 +33,7 @@ import kotlin.math.min /** * Utility class to import/export the crypto data */ -object MXMegolmExportEncryption { +internal object MXMegolmExportEncryption { private const val HEADER_LINE = "-----BEGIN MEGOLM SESSION DATA-----" private const val TRAILER_LINE = "-----END MEGOLM SESSION DATA-----" diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt index 501fb42db2d..4947761f05c 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MXOlmDevice.kt @@ -22,11 +22,11 @@ import kotlinx.coroutines.sync.withLock import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE import org.matrix.android.sdk.api.util.JsonDict import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXOutboundSessionInfo import org.matrix.android.sdk.internal.crypto.algorithms.megolm.SharedWithHelper -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MegolmSessionData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MegolmSessionData.kt index caff2d76f10..f6bc9a9148a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MegolmSessionData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MegolmSessionData.kt @@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass * The type of object we use for importing and exporting megolm session data. */ @JsonClass(generateAdapter = true) -data class MegolmSessionData( +internal data class MegolmSessionData( /** * The algorithm used. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt index 70846515a7d..9798d215760 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/MyDeviceInfoHolder.kt @@ -17,8 +17,8 @@ package org.matrix.android.sdk.internal.crypto import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.session.SessionScope import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt index 4aebe091c48..792c9a25dcd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OneTimeKeysUploader.kt @@ -31,7 +31,7 @@ import kotlin.math.min // The spec recommend a 5mn delay, but due to federation // or server downtime we give it a bit more time (1 hour) -const val FALLBACK_KEY_FORGET_DELAY = 60 * 60_000L +private const val FALLBACK_KEY_FORGET_DELAY = 60 * 60_000L @SessionScope internal class OneTimeKeysUploader @Inject constructor( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt index 8e13daec94e..2438e011029 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequest.kt @@ -16,10 +16,12 @@ package org.matrix.android.sdk.internal.crypto -interface OutgoingGossipingRequest { - var recipients: Map> - var requestId: String - var state: OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState + +internal interface OutgoingGossipingRequest { + val recipients: Map> + val requestId: String + val state: OutgoingGossipingRequestState // transaction id for the cancellation, if any // var cancellationTxnId: String? } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt index fd60e432604..e6f6ac50531 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingGossipingRequestManager.kt @@ -20,7 +20,9 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId import org.matrix.android.sdk.internal.crypto.util.RequestIdHelper diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt index def7a1567a9..2ba2f5c817a 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/OutgoingSecretRequest.kt @@ -17,12 +17,13 @@ package org.matrix.android.sdk.internal.crypto import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState /** * Represents an outgoing room key request */ @JsonClass(generateAdapter = true) -class OutgoingSecretRequest( +internal class OutgoingSecretRequest( // Secret Name val secretName: String?, // list of recipients for the request diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt index 89fb43ef2ed..dab806a5657 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/RoomDecryptorProvider.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.internal.crypto +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.session.crypto.NewSessionListener import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmDecryptionFactory import org.matrix.android.sdk.internal.crypto.algorithms.olm.MXOlmDecryptionFactory @@ -74,7 +76,7 @@ internal class RoomDecryptorProvider @Inject constructor( this.newSessionListener = object : NewSessionListener { override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) { // PR reviewer: the parameter has been renamed so is now in conflict with the parameter of getOrCreateRoomDecryptor - newSessionListeners.forEach { + newSessionListeners.toList().forEach { try { it.onNewSession(roomId, senderKey, sessionId) } catch (e: Throwable) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt index 3129ccae3b0..dbdea974110 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipRequestWorker.kt @@ -21,14 +21,16 @@ import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.internal.SessionManager -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest -import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt index ff206a3c968..fd472fe73bc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/SendGossipWorker.kt @@ -21,14 +21,15 @@ import androidx.work.WorkerParameters import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.failure.shouldBeRetried +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.crypto.tasks.createUniqueTxnId @@ -38,8 +39,11 @@ import org.matrix.android.sdk.internal.worker.SessionWorkerParams import timber.log.Timber import javax.inject.Inject -internal class SendGossipWorker(context: Context, params: WorkerParameters, sessionManager: SessionManager) : - SessionSafeCoroutineWorker(context, params, sessionManager, Params::class.java) { +internal class SendGossipWorker( + context: Context, + params: WorkerParameters, + sessionManager: SessionManager +) : SessionSafeCoroutineWorker(context, params, sessionManager, Params::class.java) { @JsonClass(generateAdapter = true) internal data class Params( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt index 87c176612d7..fffc2b4d4bb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForDevicesAction.kt @@ -21,11 +21,11 @@ import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.MXOlmDevice -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.MXKey import org.matrix.android.sdk.internal.crypto.model.MXOlmSessionResult -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.tasks.ClaimOneTimeKeysForUsersDeviceTask import org.matrix.android.sdk.internal.session.SessionScope import timber.log.Timber diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt index a3cfbd91f00..fc211537a68 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/EnsureOlmSessionsForUsersAction.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.crypto.actions +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.model.MXOlmSessionResult -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import timber.log.Timber import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt index f79b97b0818..f9bcdf2c680 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MegolmSessionDataImporter.kt @@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.crypto.actions import androidx.annotation.WorkerThread import org.matrix.android.sdk.api.listeners.ProgressListener +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.RoomDecryptorProvider import org.matrix.android.sdk.internal.crypto.algorithms.megolm.MXMegolmDecryption -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import timber.log.Timber import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt index 4e158602c89..9bbbab4992a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/MessageEncrypter.kt @@ -16,11 +16,11 @@ package org.matrix.android.sdk.internal.crypto.actions +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_OLM import org.matrix.android.sdk.api.logger.LoggerTag +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.events.model.Content -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_OLM import org.matrix.android.sdk.internal.crypto.MXOlmDevice -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedMessage import org.matrix.android.sdk.internal.di.DeviceId import org.matrix.android.sdk.internal.di.UserId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt index 40eddc82bd0..60181138fb9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/actions/SetDeviceVerificationAction.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto.actions -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.di.UserId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt index 51ddd744422..2ea4e1dd29f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXDecrypting.kt @@ -17,10 +17,10 @@ package org.matrix.android.sdk.internal.crypto.algorithms import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt index 91f10adf4c0..585bcdbbdef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/IMXWithHeldExtension.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto.algorithms -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent internal interface IMXWithHeldExtension { fun onRoomKeyWithHeldEvent(withHeldInfo: RoomKeyWithHeldContent) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt index 72df59023a3..4c407c9eb96 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmDecryption.kt @@ -23,26 +23,26 @@ import kotlinx.coroutines.sync.withLock import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.model.ForwardedRoomKeyContent +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyContent +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.internal.crypto.DeviceListManager -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult import org.matrix.android.sdk.internal.crypto.MXOlmDevice -import org.matrix.android.sdk.internal.crypto.NewSessionListener import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting import org.matrix.android.sdk.internal.crypto.algorithms.IMXWithHeldExtension import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask import org.matrix.android.sdk.internal.session.StreamEventsManager diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt index cf9733dc2dc..f0521942304 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXMegolmEncryption.kt @@ -21,24 +21,24 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.forEach import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode import org.matrix.android.sdk.internal.crypto.DeviceListManager -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForDevicesAction import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting import org.matrix.android.sdk.internal.crypto.algorithms.IMXGroupEncryption import org.matrix.android.sdk.internal.crypto.keysbackup.DefaultKeysBackupService -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode -import org.matrix.android.sdk.internal.crypto.model.forEach import org.matrix.android.sdk.internal.crypto.model.toDebugCount import org.matrix.android.sdk.internal.crypto.model.toDebugString import org.matrix.android.sdk.internal.crypto.repository.WarnOnUnknownDeviceRepository diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt index b70e6c1f80f..091abd49746 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/MXOutboundSessionInfo.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import timber.log.Timber internal class MXOutboundSessionInfo( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt index a64e5af0d33..59d78c3e05c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/megolm/SharedWithHelper.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.algorithms.megolm -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore internal class SharedWithHelper( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt index afa249801d9..0db8700852f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmDecryption.kt @@ -19,26 +19,27 @@ package org.matrix.android.sdk.internal.crypto.algorithms.olm import kotlinx.coroutines.sync.withLock import org.matrix.android.sdk.api.logger.LoggerTag import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent +import org.matrix.android.sdk.api.session.events.model.content.OlmPayloadContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.util.JSON_DICT_PARAMETERIZED_TYPE import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.algorithms.IMXDecrypting -import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent -import org.matrix.android.sdk.internal.crypto.model.event.OlmPayloadContent import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.convertFromUTF8 import timber.log.Timber private val loggerTag = LoggerTag("MXOlmDecryption", LoggerTag.CRYPTO) + internal class MXOlmDecryption( // The olm device interface private val olmDevice: MXOlmDevice, // the matrix userId private val userId: String) : - IMXDecrypting { + IMXDecrypting { @Throws(MXCryptoError::class) override suspend fun decryptEvent(event: Event, timeline: String): MXEventDecryptionResult { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt index 63f2533ac32..7fdfd5a2876 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/algorithms/olm/MXOlmEncryption.kt @@ -16,6 +16,7 @@ package org.matrix.android.sdk.internal.crypto.algorithms.olm +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.internal.crypto.DeviceListManager @@ -23,7 +24,6 @@ import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.actions.EnsureOlmSessionsForUsersAction import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter import org.matrix.android.sdk.internal.crypto.algorithms.IMXEncrypting -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore internal class MXOlmEncryption( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt index cef86e8b5ec..f21f5e05e14 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/api/CryptoApi.kt @@ -15,9 +15,9 @@ */ package org.matrix.android.sdk.internal.crypto.api +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.DeleteDeviceParams -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.crypto.model.rest.KeyChangesResponse import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimBody import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimResponse diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt index ba5baba60d4..80090cf4a8a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/EncryptionResult.kt @@ -16,12 +16,12 @@ package org.matrix.android.sdk.internal.crypto.attachments -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo /** * Define the result of an encryption file */ internal data class EncryptionResult( - var encryptedFileInfo: EncryptedFileInfo, - var encryptedByteArray: ByteArray + val encryptedFileInfo: EncryptedFileInfo, + val encryptedByteArray: ByteArray ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt index 70730326da1..91b6af6fc3a 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MXEncryptedAttachments.kt @@ -17,8 +17,9 @@ package org.matrix.android.sdk.internal.crypto.attachments import android.util.Base64 -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo -import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo +import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey import org.matrix.android.sdk.internal.util.base64ToBase64Url import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64 import org.matrix.android.sdk.internal.util.base64UrlToBase64 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt deleted file mode 100644 index 2cbe0e37027..00000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/attachments/MatrixDigestCheckInputStream.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020 The Matrix.org Foundation C.I.C. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.android.sdk.internal.crypto.attachments - -import android.util.Base64 -import org.matrix.android.sdk.internal.util.base64ToUnpaddedBase64 -import java.io.FilterInputStream -import java.io.IOException -import java.io.InputStream -import java.security.MessageDigest - -class MatrixDigestCheckInputStream( - inputStream: InputStream?, - private val expectedDigest: String -) : FilterInputStream(inputStream) { - - private val digest = MessageDigest.getInstance("SHA-256") - - @Throws(IOException::class) - override fun read(): Int { - val b = `in`.read() - if (b >= 0) { - digest.update(b.toByte()) - } - - if (b == -1) { - ensureDigest() - } - return b - } - - @Throws(IOException::class) - override fun read( - b: ByteArray, - off: Int, - len: Int): Int { - val n = `in`.read(b, off, len) - if (n > 0) { - digest.update(b, off, n) - } - - if (n == -1) { - ensureDigest() - } - return n - } - - @Throws(IOException::class) - private fun ensureDigest() { - val currentDigestValue = base64ToUnpaddedBase64(Base64.encodeToString(digest.digest(), Base64.DEFAULT)) - if (currentDigestValue != expectedDigest) { - throw IOException("Bad digest") - } - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/ComputeTrustTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/ComputeTrustTask.kt index b470ab34bb7..02ea9432848 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/ComputeTrustTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/ComputeTrustTask.kt @@ -17,9 +17,9 @@ package org.matrix.android.sdk.internal.crypto.crosssigning import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt index 83de06a6687..ba1718688fd 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/DefaultCrossSigningService.kt @@ -26,13 +26,20 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustResult import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.UserTrustResult +import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerified +import org.matrix.android.sdk.api.session.crypto.crosssigning.isLocallyVerified +import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.util.Optional +import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.internal.crypto.DeviceListManager -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.UploadSignatureQueryBuilder import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo import org.matrix.android.sdk.internal.crypto.tasks.InitializeCrossSigningTask import org.matrix.android.sdk.internal.crypto.tasks.UploadSignaturesTask import org.matrix.android.sdk.internal.di.SessionId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/Extensions.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/Extensions.kt index cf2d6aa2693..16098e5210a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/Extensions.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/Extensions.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.crosssigning import android.util.Base64 -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.util.JsonCanonicalizer import timber.log.Timber @@ -29,14 +29,6 @@ internal fun CryptoCrossSigningKey.canonicalSignable(): String { return JsonCanonicalizer.getCanonicalJson(Map::class.java, signalableJSONDictionary()) } -fun ByteArray.toBase64NoPadding(): String { - return Base64.encodeToString(this, Base64.NO_PADDING or Base64.NO_WRAP) -} - -fun String.fromBase64(): ByteArray { - return Base64.decode(this, Base64.DEFAULT) -} - /** * Decode the base 64. Return null in case of bad format. Should be used when parsing received data from external source */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt index 794ab045332..74f0f5745d3 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/crosssigning/UpdateTrustWorker.kt @@ -22,9 +22,12 @@ import com.squareup.moshi.JsonClass import io.realm.Realm import io.realm.RealmConfiguration import io.realm.kotlin.where -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.UserTrustResult +import org.matrix.android.sdk.api.session.crypto.crosssigning.isCrossSignedVerified +import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt index 954c2dbe431..e63a6dc791c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/DefaultKeysBackupService.kt @@ -28,30 +28,37 @@ import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.data.Credentials +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.StepProgressListener +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrustSignature +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey +import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey +import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult +import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.android.sdk.internal.crypto.ObjectSigner import org.matrix.android.sdk.internal.crypto.actions.MegolmSessionDataImporter -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust -import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrustSignature -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo import org.matrix.android.sdk.internal.crypto.keysbackup.model.SignalableMegolmBackupAuthData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeyBackupData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysBackupData -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.RoomKeysBackupData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.CreateKeysBackupVersionTask @@ -68,12 +75,8 @@ import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionD import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreRoomSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.StoreSessionsDataTask import org.matrix.android.sdk.internal.crypto.keysbackup.tasks.UpdateKeysBackupVersionTask -import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey -import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey -import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.di.UserId @@ -84,7 +87,6 @@ import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.task.TaskThread import org.matrix.android.sdk.internal.task.configureWith import org.matrix.android.sdk.internal.util.JsonCanonicalizer -import org.matrix.android.sdk.internal.util.awaitCallback import org.matrix.olm.OlmException import org.matrix.olm.OlmPkDecryption import org.matrix.olm.OlmPkEncryption @@ -407,20 +409,22 @@ internal class DefaultKeysBackupService @Inject constructor( */ @WorkerThread private fun getKeysBackupTrustBg(keysBackupVersion: KeysVersionResult): KeysBackupVersionTrust { - val keysBackupVersionTrust = KeysBackupVersionTrust() val authData = keysBackupVersion.getAuthDataAsMegolmBackupAuthData() if (authData == null || authData.publicKey.isEmpty() || authData.signatures.isNullOrEmpty()) { Timber.v("getKeysBackupTrust: Key backup is absent or missing required data") - return keysBackupVersionTrust + return KeysBackupVersionTrust(usable = false) } val mySigs = authData.signatures[userId] if (mySigs.isNullOrEmpty()) { Timber.v("getKeysBackupTrust: Ignoring key backup because it lacks any signatures from this user") - return keysBackupVersionTrust + return KeysBackupVersionTrust(usable = false) } + var keysBackupVersionTrustIsUsable = false + val keysBackupVersionTrustSignatures = mutableListOf() + for ((keyId, mySignature) in mySigs) { // XXX: is this how we're supposed to get the device id? var deviceId: String? = null @@ -447,19 +451,23 @@ internal class DefaultKeysBackupService @Inject constructor( } if (isSignatureValid && device.isVerified) { - keysBackupVersionTrust.usable = true + keysBackupVersionTrustIsUsable = true } } - val signature = KeysBackupVersionTrustSignature() - signature.device = device - signature.valid = isSignatureValid - signature.deviceId = deviceId - keysBackupVersionTrust.signatures.add(signature) + val signature = KeysBackupVersionTrustSignature( + deviceId = deviceId, + device = device, + valid = isSignatureValid, + ) + keysBackupVersionTrustSignatures.add(signature) } } - return keysBackupVersionTrust + return KeysBackupVersionTrust( + usable = keysBackupVersionTrustIsUsable, + signatures = keysBackupVersionTrustSignatures + ) } override fun trustKeysBackupVersion(keysBackupVersion: KeysVersionResult, @@ -586,21 +594,28 @@ internal class DefaultKeysBackupService @Inject constructor( cryptoCoroutineScope.launch(coroutineDispatchers.main) { try { - val keysBackupVersion = getKeysBackupLastVersionTask.execute(Unit) - val recoveryKey = computeRecoveryKey(secret.fromBase64()) - if (isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) { - awaitCallback { - trustKeysBackupVersion(keysBackupVersion, true, it) + when (val keysBackupLastVersionResult = getKeysBackupLastVersionTask.execute(Unit)) { + KeysBackupLastVersionResult.NoKeysBackup -> { + Timber.d("No keys backup found") } - val importResult = awaitCallback { - restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it) - } - withContext(coroutineDispatchers.crypto) { - cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version) + is KeysBackupLastVersionResult.KeysBackup -> { + val keysBackupVersion = keysBackupLastVersionResult.keysVersionResult + val recoveryKey = computeRecoveryKey(secret.fromBase64()) + if (isValidRecoveryKeyForKeysBackupVersion(recoveryKey, keysBackupVersion)) { + awaitCallback { + trustKeysBackupVersion(keysBackupVersion, true, it) + } + val importResult = awaitCallback { + restoreKeysWithRecoveryKey(keysBackupVersion, recoveryKey, null, null, null, it) + } + withContext(coroutineDispatchers.crypto) { + cryptoStore.saveBackupRecoveryKey(recoveryKey, keysBackupVersion.version) + } + Timber.i("onSecretKeyGossip: Recovered keys $importResult") + } else { + Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}") + } } - Timber.i("onSecretKeyGossip: Recovered keys ${importResult.successfullyNumberOfImportedKeys} out of ${importResult.totalNumberOfKeys}") - } else { - Timber.e("onSecretKeyGossip: Recovery key is not valid ${keysBackupVersion.version}") } } catch (failure: Throwable) { Timber.e("onSecretKeyGossip: failed to trust key backup version ${keysBackupVersion?.version}") @@ -875,63 +890,49 @@ internal class DefaultKeysBackupService @Inject constructor( .executeBy(taskExecutor) } - override fun getCurrentVersion(callback: MatrixCallback) { + override fun getCurrentVersion(callback: MatrixCallback) { getKeysBackupLastVersionTask .configureWith { - this.callback = object : MatrixCallback { - override fun onSuccess(data: KeysVersionResult) { - callback.onSuccess(data) - } - - override fun onFailure(failure: Throwable) { - if (failure is Failure.ServerError && - failure.error.code == MatrixError.M_NOT_FOUND) { - // Workaround because the homeserver currently returns M_NOT_FOUND when there is no key backup - callback.onSuccess(null) - } else { - // Transmit the error - callback.onFailure(failure) - } - } - } + this.callback = callback } .executeBy(taskExecutor) } override fun forceUsingLastVersion(callback: MatrixCallback) { - getCurrentVersion(object : MatrixCallback { - override fun onSuccess(data: KeysVersionResult?) { + getCurrentVersion(object : MatrixCallback { + override fun onSuccess(data: KeysBackupLastVersionResult) { val localBackupVersion = keysBackupVersion?.version - val serverBackupVersion = data?.version - - if (serverBackupVersion == null) { - if (localBackupVersion == null) { - // No backup on the server, and backup is not active - callback.onSuccess(true) - } else { - // No backup on the server, and we are currently backing up, so stop backing up - callback.onSuccess(false) - resetKeysBackupData() - keysBackupVersion = null - keysBackupStateManager.state = KeysBackupState.Disabled - } - } else { - if (localBackupVersion == null) { - // backup on the server, and backup is not active - callback.onSuccess(false) - // Do a check - checkAndStartWithKeysBackupVersion(data) - } else { - // Backup on the server, and we are currently backing up, compare version - if (localBackupVersion == serverBackupVersion) { - // We are already using the last version of the backup + when (data) { + KeysBackupLastVersionResult.NoKeysBackup -> { + if (localBackupVersion == null) { + // No backup on the server, and backup is not active callback.onSuccess(true) } else { - // We are not using the last version, so delete the current version we are using on the server + // No backup on the server, and we are currently backing up, so stop backing up callback.onSuccess(false) + resetKeysBackupData() + keysBackupVersion = null + keysBackupStateManager.state = KeysBackupState.Disabled + } + } + is KeysBackupLastVersionResult.KeysBackup -> { + if (localBackupVersion == null) { + // backup on the server, and backup is not active + callback.onSuccess(false) + // Do a check + checkAndStartWithKeysBackupVersion(data.keysVersionResult) + } else { + // Backup on the server, and we are currently backing up, compare version + if (localBackupVersion == data.keysVersionResult.version) { + // We are already using the last version of the backup + callback.onSuccess(true) + } else { + // We are not using the last version, so delete the current version we are using on the server + callback.onSuccess(false) - // This will automatically check for the last version then - deleteBackup(localBackupVersion, null) + // This will automatically check for the last version then + deleteBackup(localBackupVersion, null) + } } } } @@ -954,9 +955,9 @@ internal class DefaultKeysBackupService @Inject constructor( keysBackupVersion = null keysBackupStateManager.state = KeysBackupState.CheckingBackUpOnHomeserver - getCurrentVersion(object : MatrixCallback { - override fun onSuccess(data: KeysVersionResult?) { - checkAndStartWithKeysBackupVersion(data) + getCurrentVersion(object : MatrixCallback { + override fun onSuccess(data: KeysBackupLastVersionResult) { + checkAndStartWithKeysBackupVersion(data.toKeysVersionResult()) } override fun onFailure(failure: Throwable) { @@ -1104,6 +1105,13 @@ internal class DefaultKeysBackupService @Inject constructor( } } + override fun computePrivateKey(passphrase: String, + privateKeySalt: String, + privateKeyIterations: Int, + progressListener: ProgressListener): ByteArray { + return deriveKey(passphrase, privateKeySalt, privateKeyIterations, progressListener) + } + /** * Enable backing up of keys. * This method will update the state and will start sending keys in nominal case diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt index 24c3942055d..c12879dbeeb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/KeysBackupPassword.kt @@ -30,13 +30,14 @@ import kotlin.experimental.xor private const val SALT_LENGTH = 32 private const val DEFAULT_ITERATION = 500_000 -data class GeneratePrivateKeyResult( +internal data class GeneratePrivateKeyResult( // The private key val privateKey: ByteArray, // the salt used to generate the private key val salt: String, // number of key derivations done on the generated private key. - val iterations: Int) + val iterations: Int +) /** * Compute a private key from a password. @@ -46,7 +47,9 @@ data class GeneratePrivateKeyResult( * @return a {privateKey, salt, iterations} tuple. */ @WorkerThread -fun generatePrivateKeyWithPassword(password: String, progressListener: ProgressListener?): GeneratePrivateKeyResult { +internal fun generatePrivateKeyWithPassword(password: String, + progressListener: ProgressListener? +): GeneratePrivateKeyResult { val salt = generateSalt() val iterations = DEFAULT_ITERATION val privateKey = deriveKey(password, salt, iterations, progressListener) @@ -65,10 +68,10 @@ fun generatePrivateKeyWithPassword(password: String, progressListener: ProgressL * @return a private key. */ @WorkerThread -fun retrievePrivateKeyWithPassword(password: String, - salt: String, - iterations: Int, - progressListener: ProgressListener? = null): ByteArray { +internal fun retrievePrivateKeyWithPassword(password: String, + salt: String, + iterations: Int, + progressListener: ProgressListener? = null): ByteArray { return deriveKey(password, salt, iterations, progressListener) } @@ -83,10 +86,10 @@ fun retrievePrivateKeyWithPassword(password: String, * @return a private key. */ @WorkerThread -fun deriveKey(password: String, - salt: String, - iterations: Int, - progressListener: ProgressListener?): ByteArray { +internal fun deriveKey(password: String, + salt: String, + iterations: Int, + progressListener: ProgressListener?): ByteArray { // Note: copied and adapted from MXMegolmExportEncryption val t0 = System.currentTimeMillis() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt index eb4c55a3e7f..8464b33526f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/api/RoomKeysApi.kt @@ -16,12 +16,12 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.api +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.BackupKeysResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeyBackupData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysBackupData -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.RoomKeysBackupData import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.UpdateKeysBackupVersionBody import org.matrix.android.sdk.internal.network.NetworkConstants diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrust.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrust.kt deleted file mode 100644 index 07ca87fe33b..00000000000 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrust.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 The Matrix.org Foundation C.I.C. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.android.sdk.internal.crypto.keysbackup.model - -import com.squareup.moshi.JsonClass - -/** - * Data model for response to [KeysBackup.isKeyBackupTrusted()]. - */ -@JsonClass(generateAdapter = true) -data class KeyBackupVersionTrust( - /** - * Flag to indicate if the backup is trusted. - * true if there is a signature that is valid & from a trusted device. - */ - var usable: Boolean = false, - - /** - * Signatures found in the backup version. - */ - var signatures: MutableList = ArrayList() -) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrustSignature.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/SignalableMegolmBackupAuthData.kt similarity index 56% rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrustSignature.kt rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/SignalableMegolmBackupAuthData.kt index 5256c781762..85f75a61e2d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/KeyBackupVersionTrustSignature.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/SignalableMegolmBackupAuthData.kt @@ -16,20 +16,21 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.util.JsonDict -/** - * A signature in a the `KeyBackupVersionTrust` object. - */ -class KeyBackupVersionTrustSignature { - - /** - * The device that signed the backup version. - */ - var device: CryptoDeviceInfo? = null +internal data class SignalableMegolmBackupAuthData( + val publicKey: String, + val privateKeySalt: String? = null, + val privateKeyIterations: Int? = null +) { + fun signalableJSONDictionary(): JsonDict = HashMap().apply { + put("public_key", publicKey) - /** - *Flag to indicate the signature from this device is valid. - */ - var valid = false + privateKeySalt?.let { + put("private_key_salt", it) + } + privateKeyIterations?.let { + put("private_key_iterations", it) + } + } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt index 3f8129b8f65..5c3d0c12b0e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeyBackupData.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.internal.network.parsing.ForceToBoolean * Backup data for one key. */ @JsonClass(generateAdapter = true) -data class KeyBackupData( +internal data class KeyBackupData( /** * Required. The index of the first message in the session that the key can decrypt. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt index e098aa0440e..898b357c517 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysAlgorithmAndData.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.model.rest +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP +import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupAuthData import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP -import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupAuthData import org.matrix.android.sdk.internal.di.MoshiProvider /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysBackupData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysBackupData.kt index 6b55f200205..42374588593 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysBackupData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/KeysBackupData.kt @@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass * Backup data for several keys in several rooms. */ @JsonClass(generateAdapter = true) -data class KeysBackupData( +internal data class KeysBackupData( // the keys are the room IDs, and the values are RoomKeysBackupData @Json(name = "rooms") val roomIdToRoomKeysBackupData: MutableMap = HashMap() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt index ce42a3bc35e..5ea6a2f890a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/RoomKeysBackupData.kt @@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass * Backup data for several keys within a room. */ @JsonClass(generateAdapter = true) -data class RoomKeysBackupData( +internal data class RoomKeysBackupData( // the keys are the session IDs, and the values are KeyBackupData @Json(name = "sessions") val sessionIdToKeyBackupData: MutableMap = HashMap() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt index 4512ed7a55a..3f2def84d55 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/model/rest/UpdateKeysBackupVersionBody.kt @@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass import org.matrix.android.sdk.api.util.JsonDict @JsonClass(generateAdapter = true) -data class UpdateKeysBackupVersionBody( +internal data class UpdateKeysBackupVersionBody( /** * The algorithm used for storing backups. Currently, only "m.megolm_backup.v1.curve25519-aes-sha2" is defined */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt index 62610a0b7bd..10d6e923e7b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/CreateKeysBackupVersionTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.CreateKeysBackupVersionBody -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt index 54dbf85e302..e5621c0cb5c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupLastVersionTask.kt @@ -16,23 +16,34 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks +import org.matrix.android.sdk.api.failure.is404 +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task import javax.inject.Inject -internal interface GetKeysBackupLastVersionTask : Task +internal interface GetKeysBackupLastVersionTask : Task internal class DefaultGetKeysBackupLastVersionTask @Inject constructor( private val roomKeysApi: RoomKeysApi, private val globalErrorReceiver: GlobalErrorReceiver ) : GetKeysBackupLastVersionTask { - override suspend fun execute(params: Unit): KeysVersionResult { - return executeRequest(globalErrorReceiver) { - roomKeysApi.getKeysBackupLastVersion() + override suspend fun execute(params: Unit): KeysBackupLastVersionResult { + return try { + val keysVersionResult = executeRequest(globalErrorReceiver) { + roomKeysApi.getKeysBackupLastVersion() + } + KeysBackupLastVersionResult.KeysBackup(keysVersionResult) + } catch (throwable: Throwable) { + if (throwable.is404()) { + KeysBackupLastVersionResult.NoKeysBackup + } else { + // Propagate other errors + throw throwable + } } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt index 390873eb68d..fe1ca297981 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/tasks/GetKeysBackupVersionTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.keysbackup.tasks +import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult import org.matrix.android.sdk.internal.crypto.keysbackup.api.RoomKeysApi -import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt index def9c1b6757..0e746f289b8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/Base58.kt @@ -41,7 +41,7 @@ private val BASE = BigInteger.valueOf(58) /** * Encode a byte array to a human readable string with base58 chars */ -fun base58encode(input: ByteArray): String { +internal fun base58encode(input: ByteArray): String { var bi = BigInteger(1, input) val s = StringBuffer() while (bi >= BASE) { @@ -64,7 +64,7 @@ fun base58encode(input: ByteArray): String { /** * Decode a base58 String to a byte array */ -fun base58decode(input: String): ByteArray { +internal fun base58decode(input: String): ByteArray { var result = decodeToBigInteger(input).toByteArray() // Remove the first leading zero if any diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoDeviceInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoDeviceInfo.kt index b3638dc414d..727f7398664 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoDeviceInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoDeviceInfo.kt @@ -15,64 +15,8 @@ */ package org.matrix.android.sdk.internal.crypto.model -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceKeys -import org.matrix.android.sdk.internal.crypto.model.rest.UnsignedDeviceInfo - -data class CryptoDeviceInfo( - val deviceId: String, - override val userId: String, - var algorithms: List? = null, - override val keys: Map? = null, - override val signatures: Map>? = null, - val unsigned: UnsignedDeviceInfo? = null, - var trustLevel: DeviceTrustLevel? = null, - var isBlocked: Boolean = false, - val firstTimeSeenLocalTs: Long? = null -) : CryptoInfo { - - val isVerified: Boolean - get() = trustLevel?.isVerified() == true - - val isUnknown: Boolean - get() = trustLevel == null - - /** - * @return the fingerprint - */ - fun fingerprint(): String? { - return keys - ?.takeIf { deviceId.isNotBlank() } - ?.get("ed25519:$deviceId") - } - - /** - * @return the identity key - */ - fun identityKey(): String? { - return keys - ?.takeIf { deviceId.isNotBlank() } - ?.get("curve25519:$deviceId") - } - - /** - * @return the display name - */ - fun displayName(): String? { - return unsigned?.deviceDisplayName - } - - override fun signalableJSONDictionary(): Map { - val map = HashMap() - map["device_id"] = deviceId - map["user_id"] = userId - algorithms?.let { map["algorithms"] = it } - keys?.let { map["keys"] = it } - return map - } - - fun shortDebugString() = "$userId|$deviceId" -} internal fun CryptoDeviceInfo.toRest(): DeviceKeys { return CryptoInfoMapper.map(this) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfo.kt index 39981e01f7f..e49f17262cf 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfo.kt @@ -20,7 +20,7 @@ package org.matrix.android.sdk.internal.crypto.model * Generic crypto info. * Can be a device (CryptoDeviceInfo), as well as a CryptoCrossSigningInfo (can be seen as a kind of virtual device) */ -interface CryptoInfo { +internal interface CryptoInfo { val userId: String diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfoMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfoMapper.kt index 6cc6f5400ff..de9b3f24fff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfoMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/CryptoInfoMapper.kt @@ -15,6 +15,8 @@ */ package org.matrix.android.sdk.internal.crypto.model +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.rest.DeviceKeys import org.matrix.android.sdk.internal.crypto.model.rest.DeviceKeysWithUnsigned import org.matrix.android.sdk.internal.crypto.model.rest.RestKeyInfo diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt index 9f425eee7ff..cff713bf8f7 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXKey.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.model import org.matrix.android.sdk.api.util.JsonDict import timber.log.Timber -data class MXKey( +internal data class MXKey( /** * The type of the key (in the example: "signed_curve25519"). */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt index b07a08c30f7..671827799e2 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXOlmSessionResult.kt @@ -16,9 +16,10 @@ package org.matrix.android.sdk.internal.crypto.model +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import java.io.Serializable -data class MXOlmSessionResult( +internal data class MXOlmSessionResult( /** * the device */ @@ -27,4 +28,5 @@ data class MXOlmSessionResult( * Base64 olm session id. * null if no session could be established. */ - var sessionId: String?) : Serializable + var sessionId: String? +) : Serializable diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXUsersDevicesMap.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXUsersDevicesMap.kt index bdb00dce8e6..58aff14a3dc 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXUsersDevicesMap.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/MXUsersDevicesMap.kt @@ -16,119 +16,7 @@ package org.matrix.android.sdk.internal.crypto.model -class MXUsersDevicesMap { - - // A map of maps (userId -> (deviceId -> Object)). - val map = HashMap>() - - /** - * @return the user Ids - */ - val userIds: List - get() = map.keys.toList() - - val isEmpty: Boolean - get() = map.isEmpty() - - /** - * Provides the device ids list for a user id - * FIXME Should maybe return emptyList and not null, to avoid many !! in the code - * - * @param userId the user id - * @return the device ids list - */ - fun getUserDeviceIds(userId: String?): List? { - return if (!userId.isNullOrBlank() && map.containsKey(userId)) { - map[userId]!!.keys.toList() - } else null - } - - /** - * Provides the object for a device id and a user Id - * - * @param deviceId the device id - * @param userId the object id - * @return the object - */ - fun getObject(userId: String?, deviceId: String?): E? { - return if (!userId.isNullOrBlank() && !deviceId.isNullOrBlank()) { - map[userId]?.get(deviceId) - } else null - } - - /** - * Set an object for a dedicated user Id and device Id - * - * @param userId the user Id - * @param deviceId the device id - * @param o the object to set - */ - fun setObject(userId: String?, deviceId: String?, o: E?) { - if (null != o && userId?.isNotBlank() == true && deviceId?.isNotBlank() == true) { - val devices = map.getOrPut(userId) { HashMap() } - devices[deviceId] = o - } - } - - /** - * Defines the objects map for a user Id - * - * @param objectsPerDevices the objects maps - * @param userId the user id - */ - fun setObjects(userId: String?, objectsPerDevices: Map?) { - if (!userId.isNullOrBlank()) { - if (null == objectsPerDevices) { - map.remove(userId) - } else { - map[userId] = HashMap(objectsPerDevices) - } - } - } - - /** - * Removes objects for a dedicated user - * - * @param userId the user id. - */ - fun removeUserObjects(userId: String?) { - if (!userId.isNullOrBlank()) { - map.remove(userId) - } - } - - /** - * Clear the internal dictionary - */ - fun removeAllObjects() { - map.clear() - } - - /** - * Add entries from another MXUsersDevicesMap - * - * @param other the other one - */ - fun addEntriesFromMap(other: MXUsersDevicesMap?) { - if (null != other) { - map.putAll(other.map) - } - } - - override fun toString(): String { - return "MXUsersDevicesMap $map" - } -} - -inline fun MXUsersDevicesMap.forEach(action: (String, String, T) -> Unit) { - userIds.forEach { userId -> - getUserDeviceIds(userId)?.forEach { deviceId -> - getObject(userId, deviceId)?.let { - action(userId, deviceId, it) - } - } - } -} +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap internal fun MXUsersDevicesMap.toDebugString() = map.entries.joinToString { "${it.key} [${it.value.keys.joinToString { it }}]" } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt index 086a236a2bf..45ffcc66064 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto.model -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.olm.OlmInboundGroupSession import timber.log.Timber @@ -26,7 +26,7 @@ import java.io.Serializable * This class adds more context to a OlmInboundGroupSession object. * This allows additional checks. The class implements Serializable so that the context can be stored. */ -class OlmInboundGroupSessionWrapper : Serializable { +internal class OlmInboundGroupSessionWrapper : Serializable { // The associated olm inbound group session. var olmInboundGroupSession: OlmInboundGroupSession? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt index 1dc27c75ca3..1f671aa8962 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmInboundGroupSessionWrapper2.kt @@ -16,7 +16,7 @@ package org.matrix.android.sdk.internal.crypto.model -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.MegolmSessionData import org.matrix.olm.OlmInboundGroupSession import timber.log.Timber @@ -26,7 +26,7 @@ import java.io.Serializable * This class adds more context to a OlmInboundGroupSession object. * This allows additional checks. The class implements Serializable so that the context can be stored. */ -class OlmInboundGroupSessionWrapper2 : Serializable { +internal class OlmInboundGroupSessionWrapper2 : Serializable { // The associated olm inbound group session. var olmInboundGroupSession: OlmInboundGroupSession? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt index 263cb3b0362..927d049eca9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OlmSessionWrapper.kt @@ -22,7 +22,7 @@ import org.matrix.olm.OlmSession /** * Encapsulate a OlmSession and a last received message Timestamp */ -data class OlmSessionWrapper( +internal data class OlmSessionWrapper( // The associated olm session. val olmSession: OlmSession, // Timestamp at which the session last received a message. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OutboundGroupSessionWrapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OutboundGroupSessionWrapper.kt index b616284e14a..4ac87f44cef 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OutboundGroupSessionWrapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/OutboundGroupSessionWrapper.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.model import org.matrix.olm.OlmOutboundGroupSession -data class OutboundGroupSessionWrapper( +internal data class OutboundGroupSessionWrapper( val outboundGroupSession: OlmOutboundGroupSession, val creationTime: Long ) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeys.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeys.kt index 3a845b1f2a7..611d9b72b50 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeys.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeys.kt @@ -20,7 +20,7 @@ import com.squareup.moshi.Json import com.squareup.moshi.JsonClass @JsonClass(generateAdapter = true) -data class DeviceKeys( +internal data class DeviceKeys( /** * Required. The ID of the user the device belongs to. Must match the user ID used when logging in. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeysWithUnsigned.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeysWithUnsigned.kt index 35fce323940..32f577c99b9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeysWithUnsigned.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/DeviceKeysWithUnsigned.kt @@ -18,9 +18,10 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo @JsonClass(generateAdapter = true) -data class DeviceKeysWithUnsigned( +internal data class DeviceKeysWithUnsigned( /** * Required. The ID of the user the device belongs to. Must match the user ID used when logging in. */ diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedMessage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedMessage.kt index f32676a919f..c2f76f9dea8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedMessage.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/EncryptedMessage.kt @@ -18,9 +18,10 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject @JsonClass(generateAdapter = true) -data class EncryptedMessage( +internal data class EncryptedMessage( @Json(name = "algorithm") val algorithm: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingDefaultContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingDefaultContent.kt new file mode 100644 index 00000000000..8f789a638cf --- /dev/null +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/GossipingDefaultContent.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2022 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.matrix.android.sdk.internal.crypto.model.rest + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject + +@JsonClass(generateAdapter = true) +internal data class GossipingDefaultContent( + @Json(name = "action") override val action: String?, + @Json(name = "requesting_device_id") override val requestingDeviceId: String?, + @Json(name = "m.request_id") override val requestId: String? = null +) : GossipingToDeviceObject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt index f695425c2ab..7a5773bf24d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationAccept.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAccept import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoAcceptFactory diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt index 4dfa5984dfd..90272bf0e4b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationCancel.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoCancel diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationDone.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationDone.kt index 96afba060b6..e3907914ac4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationDone.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationDone.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoDone /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt index 7ded437cea9..19d8c32ddf7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationKey.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKey import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoKeyFactory diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationMac.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationMac.kt index 6c055aee2a8..5335428c0f0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationMac.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationMac.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMac import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoMacFactory diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationReady.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationReady.kt index 3562613c2e5..e6770be9a07 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationReady.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationReady.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoReady /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationRequest.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationRequest.kt index c30b2a306ff..191d5abb60f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationRequest.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationRequest.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoRequest /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationStart.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationStart.kt index 52a66a9db6f..f74bad844d6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationStart.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/KeyVerificationStart.kt @@ -17,6 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.internal.crypto.verification.VerificationInfoStart import org.matrix.android.sdk.internal.util.JsonCanonicalizer diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt index 0d41e5b648a..66247d07d1e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/RestKeyInfo.kt @@ -17,7 +17,7 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.internal.crypto.model.CryptoInfoMapper @JsonClass(generateAdapter = true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt index 820ff697461..a96534fc3af 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/ShareRequestCancellation.kt @@ -17,7 +17,8 @@ package org.matrix.android.sdk.internal.crypto.model.rest import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject.Companion.ACTION_SHARE_CANCELLATION +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject.Companion.ACTION_SHARE_CANCELLATION /** * Class representing a room key request cancellation content diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt index 1347c2f4b65..dd0ce47cd36 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/model/rest/UploadSignatureQueryBuilder.kt @@ -15,8 +15,9 @@ */ package org.matrix.android.sdk.internal.crypto.model.rest -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.toRest +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.internal.crypto.model.toRest /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt index e6d8b5e84f2..19e66635c74 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/secrets/DefaultSharedSecretStorageService.kt @@ -19,9 +19,12 @@ package org.matrix.android.sdk.internal.crypto.secrets import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.withContext import org.matrix.android.sdk.api.MatrixCoroutineDispatchers +import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 +import org.matrix.android.sdk.api.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2 import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.session.accountdata.SessionAccountDataService +import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.securestorage.EncryptedSecretContent import org.matrix.android.sdk.api.session.securestorage.IntegrityResult @@ -35,13 +38,10 @@ import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageServi import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec import org.matrix.android.sdk.api.session.securestorage.SsssPassphrase +import org.matrix.android.sdk.api.util.fromBase64 +import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager -import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2 -import org.matrix.android.sdk.internal.crypto.SSSS_ALGORITHM_CURVE25519_AES_SHA2 -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding import org.matrix.android.sdk.internal.crypto.keysbackup.generatePrivateKeyWithPassword -import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey import org.matrix.android.sdk.internal.crypto.tools.HkdfSha256 import org.matrix.android.sdk.internal.crypto.tools.withOlmDecryption import org.matrix.android.sdk.internal.di.UserId diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt index e662ff74e72..8bedb78808f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/IMXCryptoStore.kt @@ -18,25 +18,27 @@ package org.matrix.android.sdk.internal.crypto.store import androidx.lifecycle.LiveData import androidx.paging.PagedList +import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.util.Optional -import org.matrix.android.sdk.internal.crypto.GossipingRequestState -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.NewSessionListener -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestState -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntity import org.matrix.olm.OlmAccount import org.matrix.olm.OlmOutboundGroupSession diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt index 493e7fbc39e..b841e9c6e58 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/Helper.kt @@ -28,7 +28,7 @@ import java.util.zip.GZIPOutputStream /** * Get realm, invoke the action, close realm, and return the result of the action */ -fun doWithRealm(realmConfiguration: RealmConfiguration, action: (Realm) -> T): T { +internal fun doWithRealm(realmConfiguration: RealmConfiguration, action: (Realm) -> T): T { return Realm.getInstance(realmConfiguration).use { realm -> action.invoke(realm) } @@ -37,7 +37,7 @@ fun doWithRealm(realmConfiguration: RealmConfiguration, action: (Realm) -> T /** * Get realm, do the query, copy from realm, close realm, and return the copied result */ -fun doRealmQueryAndCopy(realmConfiguration: RealmConfiguration, action: (Realm) -> T?): T? { +internal fun doRealmQueryAndCopy(realmConfiguration: RealmConfiguration, action: (Realm) -> T?): T? { return Realm.getInstance(realmConfiguration).use { realm -> action.invoke(realm)?.let { realm.copyFromRealm(it) } } @@ -46,7 +46,7 @@ fun doRealmQueryAndCopy(realmConfiguration: RealmConfiguration /** * Get realm, do the list query, copy from realm, close realm, and return the copied result */ -fun doRealmQueryAndCopyList(realmConfiguration: RealmConfiguration, action: (Realm) -> Iterable): Iterable { +internal fun doRealmQueryAndCopyList(realmConfiguration: RealmConfiguration, action: (Realm) -> Iterable): Iterable { return Realm.getInstance(realmConfiguration).use { realm -> action.invoke(realm).let { realm.copyFromRealm(it) } } @@ -55,13 +55,13 @@ fun doRealmQueryAndCopyList(realmConfiguration: RealmConfigura /** * Get realm instance, invoke the action in a transaction and close realm */ -fun doRealmTransaction(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) { +internal fun doRealmTransaction(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) { Realm.getInstance(realmConfiguration).use { realm -> realm.executeTransaction { action.invoke(it) } } } -fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) { +internal fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, action: (Realm) -> Unit) { Realm.getInstance(realmConfiguration).use { realm -> realm.executeTransactionAsync { action.invoke(it) } } @@ -70,7 +70,7 @@ fun doRealmTransactionAsync(realmConfiguration: RealmConfiguration, action: (Rea /** * Serialize any Serializable object, zip it and convert to Base64 String */ -fun serializeForRealm(o: Any?): String? { +internal fun serializeForRealm(o: Any?): String? { if (o == null) { return null } @@ -88,7 +88,7 @@ fun serializeForRealm(o: Any?): String? { * Do the opposite of serializeForRealm. */ @Suppress("UNCHECKED_CAST") -fun deserializeFromRealm(string: String?): T? { +internal fun deserializeFromRealm(string: String?): T? { if (string == null) { return null } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt index 585b3d2d25c..99adbbfbae0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/RealmCryptoStore.kt @@ -25,35 +25,35 @@ import io.realm.Realm import io.realm.RealmConfiguration import io.realm.Sort import io.realm.kotlin.where +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.NewSessionListener +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo +import org.matrix.android.sdk.api.session.crypto.keysbackup.SavedKeyBackupKeyInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.api.session.events.model.Event +import org.matrix.android.sdk.api.session.events.model.content.RoomKeyWithHeldContent import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.util.Optional import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.internal.crypto.GossipRequestType -import org.matrix.android.sdk.internal.crypto.GossipingRequestState -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.internal.crypto.NewSessionListener -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestState -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.OlmInboundGroupSessionWrapper2 import org.matrix.android.sdk.internal.crypto.model.OlmSessionWrapper import org.matrix.android.sdk.internal.crypto.model.OutboundGroupSessionWrapper -import org.matrix.android.sdk.internal.crypto.model.event.RoomKeyWithHeldContent -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore -import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo -import org.matrix.android.sdk.internal.crypto.store.SavedKeyBackupKeyInfo import org.matrix.android.sdk.internal.crypto.store.db.mapper.CrossSigningKeysMapper import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntity import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt index c15414a8dd3..5e4b9b96da8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/mapper/CrossSigningKeysMapper.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.crypto.store.db.mapper import com.squareup.moshi.Moshi import com.squareup.moshi.Types import io.realm.RealmList -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.internal.crypto.store.db.model.KeyInfoEntity import timber.log.Timber import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo001Legacy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo001Legacy.kt index 0e44689428a..7dee42e51a6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo001Legacy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo001Legacy.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.OlmSessionEntityFie import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateCryptoTo001Legacy(realm: DynamicRealm) : RealmMigrator(realm, 1) { +internal class MigrateCryptoTo001Legacy(realm: DynamicRealm) : RealmMigrator(realm, 1) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Add field lastReceivedMessageTs (Long) and set the value to 0") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo002Legacy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo002Legacy.kt index 84e627a688e..1b53e1928ad 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo002Legacy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo002Legacy.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.KeysBackupDataEntit import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateCryptoTo002Legacy(realm: DynamicRealm) : RealmMigrator(realm, 2) { +internal class MigrateCryptoTo002Legacy(realm: DynamicRealm) : RealmMigrator(realm, 2) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Update IncomingRoomKeyRequestEntity format: requestBodyString field is exploded into several fields") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo003RiotX.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo003RiotX.kt index b468a56af6e..34d1afa2d86 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo003RiotX.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo003RiotX.kt @@ -26,7 +26,7 @@ import org.matrix.androidsdk.crypto.data.MXDeviceInfo import org.matrix.androidsdk.crypto.data.MXOlmInboundGroupSession2 import timber.log.Timber -class MigrateCryptoTo003RiotX(realm: DynamicRealm) : RealmMigrator(realm, 3) { +internal class MigrateCryptoTo003RiotX(realm: DynamicRealm) : RealmMigrator(realm, 3) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Migrate to RiotX model") @@ -40,7 +40,7 @@ class MigrateCryptoTo003RiotX(realm: DynamicRealm) : RealmMigrator(realm, 3) { try { val oldSerializedData = obj.getString("deviceInfoData") deserializeFromRealm(oldSerializedData)?.let { legacyMxDeviceInfo -> - val newMxDeviceInfo = org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo( + val newMxDeviceInfo = org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo( deviceId = legacyMxDeviceInfo.deviceId, userId = legacyMxDeviceInfo.userId, algorithms = legacyMxDeviceInfo.algorithms, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt index 20a4814b8d1..52d0124c2bc 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo004.kt @@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.crypto.store.db.migration import com.squareup.moshi.Moshi import com.squareup.moshi.Types import io.realm.DynamicRealm +import org.matrix.android.sdk.api.session.crypto.model.MXDeviceInfo import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.model.MXDeviceInfo import org.matrix.android.sdk.internal.crypto.store.db.deserializeFromRealm import org.matrix.android.sdk.internal.crypto.store.db.model.CrossSigningInfoEntityFields import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntityFields @@ -33,7 +33,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber // Version 4L added Cross Signing info persistence -class MigrateCryptoTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { +internal class MigrateCryptoTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { override fun doMigrate(realm: DynamicRealm) { if (realm.schema.contains("TrustLevelEntity")) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt index 8365d344644..e1d75987670 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo005.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.IncomingGossipingRe import org.matrix.android.sdk.internal.crypto.store.db.model.OutgoingGossipingRequestEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateCryptoTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) { +internal class MigrateCryptoTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) { override fun doMigrate(realm: DynamicRealm) { realm.schema.remove("OutgoingRoomKeyRequestEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo006.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo006.kt index a29a7918268..39b28985140 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo006.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo006.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntit import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateCryptoTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) { +internal class MigrateCryptoTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Updating CryptoMetadataEntity table") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt index 7ae58e7fc05..718b9787d26 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo007.kt @@ -28,7 +28,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateCryptoTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) { +internal class MigrateCryptoTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) { override fun doMigrate(realm: DynamicRealm) { Timber.d("Updating KeyInfoEntity table") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt index e3bd3f035a2..785e6a04f42 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo008.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.DeviceInfoEntityFie import org.matrix.android.sdk.internal.crypto.store.db.model.MyDeviceLastSeenInfoEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateCryptoTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) { +internal class MigrateCryptoTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("MyDeviceLastSeenInfoEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo009.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo009.kt index ed705318f9e..8d9d24dfba8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo009.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo009.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber // Fixes duplicate devices in UserEntity#devices -class MigrateCryptoTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) { +internal class MigrateCryptoTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) { override fun doMigrate(realm: DynamicRealm) { val userEntities = realm.where("UserEntity").findAll() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo010.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo010.kt index 8d69ee55588..faf0d588320 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo010.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo010.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEnti import org.matrix.android.sdk.internal.util.database.RealmMigrator // Version 10L added WithHeld Keys Info (MSC2399) -class MigrateCryptoTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) { +internal class MigrateCryptoTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("WithHeldSessionEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo011.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo011.kt index c9825a7f3d4..feaab4bb193 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo011.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo011.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoMetadataEntit import org.matrix.android.sdk.internal.util.database.RealmMigrator // Version 11L added deviceKeysSentToServer boolean to CryptoMetadataEntity -class MigrateCryptoTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) { +internal class MigrateCryptoTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("CryptoMetadataEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo012.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo012.kt index 6b1460d9d6c..4626757a06f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo012.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo012.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.OutboundGroupSessio import org.matrix.android.sdk.internal.util.database.RealmMigrator // Version 12L added outbound group session persistence -class MigrateCryptoTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) { +internal class MigrateCryptoTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) { override fun doMigrate(realm: DynamicRealm) { val outboundEntitySchema = realm.schema.create("OutboundGroupSessionInfoEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo013.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo013.kt index dc22c5f133d..dc8984da418 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo013.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo013.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber // Version 13L delete unreferenced TrustLevelEntity -class MigrateCryptoTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) { +internal class MigrateCryptoTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) { override fun doMigrate(realm: DynamicRealm) { // Use a trick to do that... Ref: https://stackoverflow.com/questions/55221366 diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo014.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo014.kt index f0089e34277..548672790a9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo014.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo014.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity import org.matrix.android.sdk.internal.util.database.RealmMigrator // Version 14L Update the way we remember key sharing -class MigrateCryptoTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) { +internal class MigrateCryptoTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("SharedSessionEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo015.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo015.kt index 465c18555a4..bca02c2e6e2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo015.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/migration/MigrateCryptoTo015.kt @@ -17,12 +17,12 @@ package org.matrix.android.sdk.internal.crypto.store.db.migration import io.realm.DynamicRealm -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.store.db.model.CryptoRoomEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator // Version 15L adds wasEncryptedOnce field to CryptoRoomEntity -class MigrateCryptoTo015(realm: DynamicRealm) : RealmMigrator(realm, 15) { +internal class MigrateCryptoTo015(realm: DynamicRealm) : RealmMigrator(realm, 15) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("CryptoRoomEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CrossSigningInfoEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CrossSigningInfoEntity.kt index 8599c972e9c..5aba9bb9ba6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CrossSigningInfoEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CrossSigningInfoEntity.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.store.db.model import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.PrimaryKey -import org.matrix.android.sdk.internal.crypto.model.KeyUsage +import org.matrix.android.sdk.api.session.crypto.crosssigning.KeyUsage import org.matrix.android.sdk.internal.extensions.clearWith internal open class CrossSigningInfoEntity( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt index 7ba986699ab..c71d5e73a22 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/CryptoMapper.kt @@ -17,14 +17,14 @@ package org.matrix.android.sdk.internal.crypto.store.db.model import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.UnsignedDeviceInfo import org.matrix.android.sdk.api.util.JsonDict -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.UnsignedDeviceInfo import org.matrix.android.sdk.internal.di.SerializeNulls import timber.log.Timber -object CryptoMapper { +internal object CryptoMapper { private val moshi = Moshi.Builder().add(SerializeNulls.JSON_ADAPTER_FACTORY).build() private val listMigrationAdapter = moshi.adapter>(Types.newParameterizedType( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt index 75094f01db5..a024e092b7c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/GossipingEventEntity.kt @@ -20,10 +20,10 @@ import com.squareup.moshi.JsonDataException import io.realm.RealmObject import io.realm.annotations.Index import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.send.SendState -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt index 4457a44cb2d..f05c8853c8d 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/IncomingGossipingRequestEntity.kt @@ -19,12 +19,12 @@ package org.matrix.android.sdk.internal.crypto.store.db.model import io.realm.RealmObject import io.realm.annotations.Index import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.model.GossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.GossipRequestType -import org.matrix.android.sdk.internal.crypto.GossipingRequestState -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest import org.matrix.android.sdk.internal.crypto.IncomingShareRequestCommon -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody internal open class IncomingGossipingRequestEntity(@Index var requestId: String? = "", @Index var typeStr: String? = null, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt index a19547fddc3..0e1278967eb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/OutgoingGossipingRequestEntity.kt @@ -21,12 +21,12 @@ import com.squareup.moshi.Types import io.realm.RealmObject import io.realm.annotations.Index import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.model.OutgoingGossipingRequestState +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyRequestBody import org.matrix.android.sdk.internal.crypto.GossipRequestType import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequest -import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestState -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest import org.matrix.android.sdk.internal.crypto.OutgoingSecretRequest -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyRequestBody import org.matrix.android.sdk.internal.di.MoshiProvider internal open class OutgoingGossipingRequestEntity( diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/WithHeldSessionEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/WithHeldSessionEntity.kt index 6d7889053b9..93048e5775c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/WithHeldSessionEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/model/WithHeldSessionEntity.kt @@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.crypto.store.db.model import io.realm.RealmObject import io.realm.annotations.Index -import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode +import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode /** * When an encrypted message is sent in a room, the megolm key might not be sent to all devices present in the room. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt index 2784e58425a..8bf9794375f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/SharedSessionQueries.kt @@ -20,7 +20,7 @@ import io.realm.Realm import io.realm.RealmResults import io.realm.kotlin.createObject import io.realm.kotlin.where -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.SharedSessionEntityFields diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/WithHeldSessionQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/WithHeldSessionQueries.kt index b8a3e361371..c253af2bf69 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/WithHeldSessionQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/store/db/query/WithHeldSessionQueries.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.store.db.query import io.realm.Realm import io.realm.kotlin.createObject import io.realm.kotlin.where -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntity import org.matrix.android.sdk.internal.crypto.store.db.model.WithHeldSessionEntityFields diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt index d5cf749db73..96848a264d2 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/ClaimOneTimeKeysForUsersDeviceTask.kt @@ -16,9 +16,9 @@ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.api.CryptoApi import org.matrix.android.sdk.internal.crypto.model.MXKey -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.KeysClaimBody import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt index 627352f5680..1e395796a98 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/EncryptEventTask.kt @@ -15,18 +15,18 @@ */ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.api.session.crypto.CryptoService +import org.matrix.android.sdk.api.session.crypto.model.MXEncryptEventContentResult +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.room.send.SendState -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult -import org.matrix.android.sdk.internal.crypto.model.MXEncryptEventContentResult +import org.matrix.android.sdk.api.util.awaitCallback import org.matrix.android.sdk.internal.database.mapper.ContentMapper import org.matrix.android.sdk.internal.session.room.send.LocalEchoRepository import org.matrix.android.sdk.internal.task.Task -import org.matrix.android.sdk.internal.util.awaitCallback import javax.inject.Inject internal interface EncryptEventTask : Task { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDeviceInfoTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDeviceInfoTask.kt index 9f20ea598de..87dbd8d1a09 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDeviceInfoTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDeviceInfoTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.internal.crypto.api.CryptoApi -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDevicesTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDevicesTask.kt index 52f9f732994..27cb17f2abe 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDevicesTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/GetDevicesTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse import org.matrix.android.sdk.internal.crypto.api.CryptoApi -import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt index e2fd54f0d87..eefdd25044e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/InitializeCrossSigningTask.kt @@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.crypto.tasks import dagger.Lazy import org.matrix.android.sdk.api.auth.UserInteractiveAuthInterceptor +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.KeyUsage +import org.matrix.android.sdk.api.util.toBase64NoPadding import org.matrix.android.sdk.internal.auth.registration.handleUIA import org.matrix.android.sdk.internal.crypto.MXOlmDevice import org.matrix.android.sdk.internal.crypto.MyDeviceInfoHolder import org.matrix.android.sdk.internal.crypto.crosssigning.canonicalSignable -import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey -import org.matrix.android.sdk.internal.crypto.model.KeyUsage import org.matrix.android.sdk.internal.crypto.model.rest.UploadSignatureQueryBuilder import org.matrix.android.sdk.internal.di.UserId import org.matrix.android.sdk.internal.task.Task diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt index c6af9b0cd1b..fc4d422360c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/SendToDeviceTask.kt @@ -16,8 +16,8 @@ package org.matrix.android.sdk.internal.crypto.tasks +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.api.CryptoApi -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceBody import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt index 6cb14ded631..0a0df11bd33 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tasks/UploadSigningKeysTask.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.internal.crypto.tasks import org.matrix.android.sdk.api.auth.UIABaseAuth import org.matrix.android.sdk.api.failure.Failure +import org.matrix.android.sdk.api.session.crypto.crosssigning.CryptoCrossSigningKey +import org.matrix.android.sdk.api.session.crypto.crosssigning.toRest import org.matrix.android.sdk.internal.crypto.api.CryptoApi -import org.matrix.android.sdk.internal.crypto.model.CryptoCrossSigningKey import org.matrix.android.sdk.internal.crypto.model.rest.UploadSigningKeysBody -import org.matrix.android.sdk.internal.crypto.model.toRest import org.matrix.android.sdk.internal.network.GlobalErrorReceiver import org.matrix.android.sdk.internal.network.executeRequest import org.matrix.android.sdk.internal.task.Task @@ -42,7 +42,7 @@ internal interface UploadSigningKeysTask : Task?) : Failure.FeatureFailure() +internal data class UploadSigningKeys(val failures: Map?) : Failure.FeatureFailure() internal class DefaultUploadSigningKeysTask @Inject constructor( private val cryptoApi: CryptoApi, diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt index 04ce0d85002..b230f0d0295 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/tools/HkdfSha256.kt @@ -26,7 +26,7 @@ import kotlin.math.ceil * HMAC-based Extract-and-Expand Key Derivation Function (HkdfSha256) * [RFC-5869] https://tools.ietf.org/html/rfc5869 */ -object HkdfSha256 { +internal object HkdfSha256 { fun deriveSecret(inputKeyMaterial: ByteArray, salt: ByteArray?, info: ByteArray, outputLength: Int): ByteArray { return expand(extract(salt, inputKeyMaterial), info, outputLength) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt index bd623575faf..28bf1d70f7f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationService.kt @@ -23,10 +23,13 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap import org.matrix.android.sdk.api.session.crypto.verification.CancelCode import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest import org.matrix.android.sdk.api.session.crypto.verification.QrCodeVerificationTransaction @@ -41,6 +44,7 @@ import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.LocalEcho import org.matrix.android.sdk.api.session.events.model.RelationType +import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent @@ -59,10 +63,6 @@ import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.MyDeviceInfoHolder import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap -import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationAccept import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationCancel import org.matrix.android.sdk.internal.crypto.model.rest.KeyVerificationDone diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt index 6043c21b665..69d9388c5ff 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/DefaultVerificationTransaction.kt @@ -17,12 +17,12 @@ package org.matrix.android.sdk.internal.crypto.verification import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.session.crypto.crosssigning.CrossSigningService +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState import org.matrix.android.sdk.internal.crypto.IncomingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.OutgoingGossipingRequestManager import org.matrix.android.sdk.internal.crypto.actions.SetDeviceVerificationAction -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel import timber.log.Timber /** diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfo.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfo.kt index 368a9b6b543..0615773a7ba 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfo.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfo.kt @@ -15,10 +15,10 @@ */ package org.matrix.android.sdk.internal.crypto.verification +import org.matrix.android.sdk.api.session.crypto.model.SendToDeviceObject import org.matrix.android.sdk.api.session.events.model.Content -import org.matrix.android.sdk.internal.crypto.model.rest.SendToDeviceObject -interface VerificationInfo { +internal interface VerificationInfo { fun toEventContent(): Content? = null fun toSendToDeviceObject(): SendToDeviceObject? = null diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt index f727aff39d3..40c96dfa959 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/crypto/verification/VerificationInfoStart.kt @@ -103,7 +103,7 @@ internal interface VerificationInfoStart : VerificationInfo CoroutineScope.asyncTransaction(realmConfiguration: RealmConfig } } -suspend fun awaitTransaction(config: RealmConfiguration, transaction: suspend (realm: Realm) -> T): T { +internal suspend fun awaitTransaction(config: RealmConfiguration, transaction: suspend (realm: Realm) -> T): T { return withContext(Realm.WRITE_EXECUTOR.asCoroutineDispatcher()) { Realm.getInstance(config).use { bgRealm -> bgRealm.beginTransaction() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt index d2e3e99b755..4fdedabd705 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ChunkEntityHelper.kt @@ -118,7 +118,7 @@ internal fun ChunkEntity.addTimelineEvent(roomId: String, return timelineEventEntity } -fun computeIsUnique( +internal fun computeIsUnique( realm: Realm, roomId: String, isLastForward: Boolean, @@ -226,6 +226,9 @@ internal fun ChunkEntity.isMoreRecentThan(chunkToCheck: ChunkEntity): Boolean { if (chunkToCheck.doesNextChunksVerifyCondition { it == this }) { return true } + if (this.doesNextChunksVerifyCondition { it == chunkToCheck }) { + return false + } // Otherwise check if this chunk is linked to last forward if (this.doesNextChunksVerifyCondition { it.isLastForward }) { return true diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt index 7087f071621..24de26eeea9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/helper/ThreadSummaryHelper.kt @@ -22,13 +22,13 @@ import io.realm.Sort import io.realm.kotlin.createObject import org.matrix.android.sdk.api.session.crypto.CryptoService import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.room.model.RoomMemberContent import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.threads.model.ThreadSummary import org.matrix.android.sdk.api.session.room.threads.model.ThreadSummaryUpdateType -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.database.mapper.asDomain import org.matrix.android.sdk.internal.database.mapper.toEntity import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt index c3302f5ccbe..3083df062e6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/EventMapper.kt @@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.database.mapper import com.squareup.moshi.JsonDataException import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.UnsignedData @@ -26,7 +27,6 @@ import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.threads.ThreadDetails import org.matrix.android.sdk.api.session.threads.ThreadNotificationState -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.database.model.EventEntity import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/RoomSummaryMapper.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/RoomSummaryMapper.kt index 63b326096a8..41faf30a82e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/RoomSummaryMapper.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/mapper/RoomSummaryMapper.kt @@ -16,7 +16,8 @@ package org.matrix.android.sdk.internal.database.mapper -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.session.room.model.RoomSummary @@ -24,7 +25,6 @@ import org.matrix.android.sdk.api.session.room.model.SpaceChildInfo import org.matrix.android.sdk.api.session.room.model.SpaceParentInfo import org.matrix.android.sdk.api.session.room.model.tag.RoomTag import org.matrix.android.sdk.api.session.typing.TypingUsersTracker -import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity import org.matrix.android.sdk.internal.database.model.presence.toUserPresence import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo001.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo001.kt index 831c6280ad5..7bed23066c5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo001.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo001.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) { +internal class MigrateSessionTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) { override fun doMigrate(realm: DynamicRealm) { // Add hasFailedSending in RoomSummary and a small warning icon on room list diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo002.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo002.kt index 215e558e2af..9fa36248f86 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo002.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo002.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.database.migration import io.realm.DynamicRealm import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) { +internal class MigrateSessionTo002(realm: DynamicRealm) : RealmMigrator(realm, 2) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("HomeServerCapabilitiesEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo003.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo003.kt index bc0b79d7e64..b4aca53ece1 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo003.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo003.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) { +internal class MigrateSessionTo003(realm: DynamicRealm) : RealmMigrator(realm, 3) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("HomeServerCapabilitiesEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo004.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo004.kt index be13ae2c2f6..0d91aab7d80 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo004.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo004.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.PendingThreePidEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { +internal class MigrateSessionTo004(realm: DynamicRealm) : RealmMigrator(realm, 4) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("PendingThreePidEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo005.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo005.kt index b4826b23a45..67e91d85cce 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo005.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo005.kt @@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.database.migration import io.realm.DynamicRealm import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) { +internal class MigrateSessionTo005(realm: DynamicRealm) : RealmMigrator(realm, 5) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("HomeServerCapabilitiesEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo006.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo006.kt index 3d7f26cceee..8eccc229e7c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo006.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo006.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) { +internal class MigrateSessionTo006(realm: DynamicRealm) : RealmMigrator(realm, 6) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("PreviewUrlCacheEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo007.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo007.kt index be8c8ce9c6d..5d1ff803679 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo007.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo007.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields import org.matrix.android.sdk.internal.database.model.RoomMembersLoadStatusType import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) { +internal class MigrateSessionTo007(realm: DynamicRealm) : RealmMigrator(realm, 7) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("RoomEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo008.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo008.kt index d46730ef701..b61bf7e6fa8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo008.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo008.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.database.model.EditAggregatedSummaryEntit import org.matrix.android.sdk.internal.database.model.EditionOfEventFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) { +internal class MigrateSessionTo008(realm: DynamicRealm) : RealmMigrator(realm, 8) { override fun doMigrate(realm: DynamicRealm) { val editionOfEventSchema = realm.schema.create("EditionOfEvent") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo009.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo009.kt index 370430b9e32..149d322f66c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo009.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo009.kt @@ -25,7 +25,7 @@ import org.matrix.android.sdk.internal.database.model.RoomTagEntityFields import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) { +internal class MigrateSessionTo009(realm: DynamicRealm) : RealmMigrator(realm, 9) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("RoomSummaryEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt index b968862d109..aae80423ac5 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo010.kt @@ -27,7 +27,7 @@ import org.matrix.android.sdk.internal.database.model.SpaceParentSummaryEntityFi import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) { +internal class MigrateSessionTo010(realm: DynamicRealm) : RealmMigrator(realm, 10) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("SpaceChildSummaryEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo011.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo011.kt index 92ee26df428..5ba201dd463 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo011.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo011.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.EventEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) { +internal class MigrateSessionTo011(realm: DynamicRealm) : RealmMigrator(realm, 11) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("EventEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo012.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo012.kt index a914cadd806..f72cd3064fb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo012.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo012.kt @@ -26,7 +26,7 @@ import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFie import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) { +internal class MigrateSessionTo012(realm: DynamicRealm) : RealmMigrator(realm, 12) { override fun doMigrate(realm: DynamicRealm) { val joinRulesContentAdapter = MoshiProvider.providesMoshi().adapter(RoomJoinRulesContent::class.java) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo013.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo013.kt index 2ea03038022..2823a69ff14 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo013.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo013.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.SpaceChildSummaryEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) { +internal class MigrateSessionTo013(realm: DynamicRealm) : RealmMigrator(realm, 13) { override fun doMigrate(realm: DynamicRealm) { // Fix issue with the nightly build. Eventually play again the migration which has been included in migrateTo12() diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo014.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo014.kt index c524b6f2849..4a27c8bb12c 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo014.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo014.kt @@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) { +internal class MigrateSessionTo014(realm: DynamicRealm) : RealmMigrator(realm, 14) { override fun doMigrate(realm: DynamicRealm) { val roomAccountDataSchema = realm.schema.create("RoomAccountDataEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo015.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo015.kt index 329964a9a40..f45f9b39b18 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo015.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo015.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.query.process import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo015(realm: DynamicRealm) : RealmMigrator(realm, 15) { +internal class MigrateSessionTo015(realm: DynamicRealm) : RealmMigrator(realm, 15) { override fun doMigrate(realm: DynamicRealm) { // fix issue with flattenParentIds on DM that kept growing with duplicate diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo016.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo016.kt index b2fa54a05c3..69f6c9f1726 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo016.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo016.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEnti import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) { +internal class MigrateSessionTo016(realm: DynamicRealm) : RealmMigrator(realm, 16) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("HomeServerCapabilitiesEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo017.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo017.kt index 95d67b9ad84..4d8db92b698 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo017.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo017.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.EventInsertEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo017(realm: DynamicRealm) : RealmMigrator(realm, 17) { +internal class MigrateSessionTo017(realm: DynamicRealm) : RealmMigrator(realm, 17) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("EventInsertEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo018.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo018.kt index b415c51d4b5..559b8979e10 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo018.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo018.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.database.model.presence.UserPresenceEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo018(realm: DynamicRealm) : RealmMigrator(realm, 18) { +internal class MigrateSessionTo018(realm: DynamicRealm) : RealmMigrator(realm, 18) { override fun doMigrate(realm: DynamicRealm) { realm.schema.create("UserPresenceEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt index d0b368be46e..d63ef62889b 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo019.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.util.Normalizer import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo019(realm: DynamicRealm, +internal class MigrateSessionTo019(realm: DynamicRealm, private val normalizer: Normalizer) : RealmMigrator(realm, 19) { override fun doMigrate(realm: DynamicRealm) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo020.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo020.kt index c7f6e3ceed4..e0075894edb 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo020.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo020.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.ChunkEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo020(realm: DynamicRealm) : RealmMigrator(realm, 20) { +internal class MigrateSessionTo020(realm: DynamicRealm) : RealmMigrator(realm, 20) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("ChunkEntity")?.apply { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo021.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo021.kt index 6b6952e6978..2f880a29dc4 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo021.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo021.kt @@ -18,14 +18,14 @@ package org.matrix.android.sdk.internal.database.migration import io.realm.DynamicRealm import org.matrix.android.sdk.api.session.events.model.EventType -import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent +import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields import org.matrix.android.sdk.internal.database.model.EventEntityFields import org.matrix.android.sdk.internal.database.model.RoomSummaryEntityFields import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo021(realm: DynamicRealm) : RealmMigrator(realm, 21) { +internal class MigrateSessionTo021(realm: DynamicRealm) : RealmMigrator(realm, 21) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("RoomSummaryEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo022.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo022.kt index e78a9d05da2..f55700d36de 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo022.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo022.kt @@ -23,7 +23,7 @@ import org.matrix.android.sdk.internal.database.model.RoomEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator import timber.log.Timber -class MigrateSessionTo022(realm: DynamicRealm) : RealmMigrator(realm, 22) { +internal class MigrateSessionTo022(realm: DynamicRealm) : RealmMigrator(realm, 22) { override fun doMigrate(realm: DynamicRealm) { val listJoinedRoomIds = realm.where("RoomEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo023.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo023.kt index 0bb8ceeaa5e..a3ce0b54146 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo023.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo023.kt @@ -22,7 +22,7 @@ import org.matrix.android.sdk.api.session.threads.ThreadNotificationState import org.matrix.android.sdk.internal.database.model.EventEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo023(realm: DynamicRealm) : RealmMigrator(realm, 23) { +internal class MigrateSessionTo023(realm: DynamicRealm) : RealmMigrator(realm, 23) { override fun doMigrate(realm: DynamicRealm) { val eventEntity = realm.schema.get("TimelineEventEntity") ?: return diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo024.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo024.kt index ff889725669..fc17bf9b289 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo024.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo024.kt @@ -20,7 +20,7 @@ import io.realm.DynamicRealm import org.matrix.android.sdk.internal.database.model.PreviewUrlCacheEntityFields import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo024(realm: DynamicRealm) : RealmMigrator(realm, 24) { +internal class MigrateSessionTo024(realm: DynamicRealm) : RealmMigrator(realm, 24) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("PreviewUrlCacheEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo025.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo025.kt index 237b016ac25..a57fd52ec1f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo025.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo025.kt @@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.database.model.HomeServerCapabilitiesEnti import org.matrix.android.sdk.internal.extensions.forceRefreshOfHomeServerCapabilities import org.matrix.android.sdk.internal.util.database.RealmMigrator -class MigrateSessionTo025(realm: DynamicRealm) : RealmMigrator(realm, 25) { +internal class MigrateSessionTo025(realm: DynamicRealm) : RealmMigrator(realm, 25) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("HomeServerCapabilitiesEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt index f108a91ecf0..35a6135ba20 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/migration/MigrateSessionTo026.kt @@ -31,7 +31,7 @@ import org.matrix.android.sdk.internal.util.database.RealmMigrator * Live thread list: using enhanced /messages api MSC3440 * Live thread timeline: using /relations api */ -class MigrateSessionTo026(realm: DynamicRealm) : RealmMigrator(realm, 26) { +internal class MigrateSessionTo026(realm: DynamicRealm) : RealmMigrator(realm, 26) { override fun doMigrate(realm: DynamicRealm) { realm.schema.get("ChunkEntity") diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt index 09be98aa960..ba80cc8302a 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/EventEntity.kt @@ -18,10 +18,10 @@ package org.matrix.android.sdk.internal.database.model import io.realm.RealmObject import io.realm.annotations.Index +import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.room.send.SendState import org.matrix.android.sdk.api.session.threads.ThreadNotificationState -import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import org.matrix.android.sdk.internal.di.MoshiProvider import org.matrix.android.sdk.internal.extensions.assertIsManaged diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt index febedc34563..cd755590be0 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/model/RoomSummaryEntity.kt @@ -20,8 +20,8 @@ import io.realm.RealmList import io.realm.RealmObject import io.realm.annotations.Index import io.realm.annotations.PrimaryKey -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.model.RoomJoinRules import org.matrix.android.sdk.api.session.room.model.RoomSummary diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt index ece46555a7e..a33ba82f7aa 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ChunkEntityQueries.kt @@ -40,6 +40,17 @@ internal fun ChunkEntity.Companion.find(realm: Realm, roomId: String, prevToken: return query.findFirst() } +internal fun ChunkEntity.Companion.findAll(realm: Realm, roomId: String, prevToken: String? = null, nextToken: String? = null): RealmResults? { + val query = where(realm, roomId) + if (prevToken != null) { + query.equalTo(ChunkEntityFields.PREV_TOKEN, prevToken) + } + if (nextToken != null) { + query.equalTo(ChunkEntityFields.NEXT_TOKEN, nextToken) + } + return query.findAll() +} + internal fun ChunkEntity.Companion.findLastForwardChunkOfRoom(realm: Realm, roomId: String): ChunkEntity? { return where(realm, roomId) .equalTo(ChunkEntityFields.IS_LAST_FORWARD, true) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt index 8cc99c3d2fd..6c587dfcae8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/query/ReadQueries.kt @@ -94,7 +94,7 @@ internal fun isReadMarkerMoreRecent(realmConfiguration: RealmConfiguration, val eventToCheckIndex = eventToCheck?.displayIndex ?: Int.MAX_VALUE eventToCheckIndex <= readMarkerIndex } else { - eventToCheckChunk?.isLastForward == false + eventToCheckChunk != null && readMarkerChunk?.isMoreRecentThan(eventToCheckChunk) == true } } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt index d9a4f1bde15..2fad2d8e786 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MatrixComponent.kt @@ -28,12 +28,14 @@ import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.HomeServerHistoryService import org.matrix.android.sdk.api.raw.RawService +import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import org.matrix.android.sdk.internal.SessionManager import org.matrix.android.sdk.internal.auth.AuthModule import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.raw.RawModule import org.matrix.android.sdk.internal.session.MockHttpInterceptor import org.matrix.android.sdk.internal.session.TestInterceptor +import org.matrix.android.sdk.internal.settings.SettingsModule import org.matrix.android.sdk.internal.task.TaskExecutor import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver import org.matrix.android.sdk.internal.util.system.SystemModule @@ -46,6 +48,7 @@ import java.io.File NetworkModule::class, AuthModule::class, RawModule::class, + SettingsModule::class, SystemModule::class, NoOpTestModule::class ]) @@ -66,6 +69,8 @@ internal interface MatrixComponent { fun rawService(): RawService + fun lightweightSettingsStorage(): LightweightSettingsStorage + fun homeServerHistoryService(): HomeServerHistoryService fun context(): Context diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt index 9e50e9efe82..10b0d4fb131 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/MoshiProvider.kt @@ -37,7 +37,7 @@ import org.matrix.android.sdk.internal.network.parsing.TlsVersionMoshiAdapter import org.matrix.android.sdk.internal.network.parsing.UriMoshiAdapter import org.matrix.android.sdk.internal.session.sync.parsing.DefaultLazyRoomSyncEphemeralJsonAdapter -object MoshiProvider { +internal object MoshiProvider { private val moshi: Moshi = Moshi.Builder() .add(UriMoshiAdapter()) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/SerializeNulls.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/SerializeNulls.kt index 0d8fdde8139..9bd197e42ed 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/SerializeNulls.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/di/SerializeNulls.kt @@ -25,7 +25,7 @@ import java.lang.reflect.Type @Retention(AnnotationRetention.RUNTIME) @JsonQualifier -annotation class SerializeNulls { +internal annotation class SerializeNulls { companion object { val JSON_ADAPTER_FACTORY: JsonAdapter.Factory = object : JsonAdapter.Factory { @Nullable diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/LiveData.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/LiveData.kt index fecbb874d0b..8f57960b952 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/LiveData.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/LiveData.kt @@ -18,35 +18,7 @@ package org.matrix.android.sdk.internal.extensions import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData -import androidx.lifecycle.MediatorLiveData -import androidx.lifecycle.Observer -inline fun LiveData.observeK(owner: LifecycleOwner, crossinline observer: (T?) -> Unit) { - this.observe(owner, Observer { observer(it) }) -} - -inline fun LiveData.observeNotNull(owner: LifecycleOwner, crossinline observer: (T) -> Unit) { - this.observe(owner, Observer { it?.run(observer) }) -} - -fun combineLatest(source1: LiveData, source2: LiveData, mapper: (T1, T2) -> R): LiveData { - val combined = MediatorLiveData() - var source1Result: T1? = null - var source2Result: T2? = null - - fun notify() { - if (source1Result != null && source2Result != null) { - combined.value = mapper(source1Result!!, source2Result!!) - } - } - - combined.addSource(source1) { - source1Result = it - notify() - } - combined.addSource(source2) { - source2Result = it - notify() - } - return combined +internal inline fun LiveData.observeNotNull(owner: LifecycleOwner, crossinline observer: (T) -> Unit) { + this.observe(owner) { it?.run(observer) } } diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt index 855e7edac3e..290f06142c6 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Primitives.kt @@ -19,4 +19,4 @@ package org.matrix.android.sdk.internal.extensions /** * Convert a signed byte to a int value */ -fun Byte.toUnsignedInt() = toInt() and 0xff +internal fun Byte.toUnsignedInt() = toInt() and 0xff diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Result.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Result.kt index 12adf16cbca..b85102ef172 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Result.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/extensions/Result.kt @@ -17,15 +17,7 @@ package org.matrix.android.sdk.internal.extensions import org.matrix.android.sdk.api.MatrixCallback -fun Result.foldToCallback(callback: MatrixCallback): Unit = fold( +internal fun Result.foldToCallback(callback: MatrixCallback): Unit = fold( { callback.onSuccess(it) }, { callback.onFailure(it) } ) - -@Suppress("UNCHECKED_CAST") // We're casting null failure results to R -inline fun Result.andThen(block: (T) -> Result): Result { - return when (val result = getOrNull()) { - null -> this as Result - else -> block(result) - } -} diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt index 22085e30fc0..0a76fb2eef7 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/DefaultLegacySessionImporter.kt @@ -26,13 +26,13 @@ import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.data.SessionParams import org.matrix.android.sdk.api.auth.data.WellKnownBaseConfig import org.matrix.android.sdk.api.legacy.LegacySessionImporter +import org.matrix.android.sdk.api.network.ssl.Fingerprint +import org.matrix.android.sdk.api.util.md5 import org.matrix.android.sdk.internal.auth.SessionParamsStore import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreMigration import org.matrix.android.sdk.internal.crypto.store.db.RealmCryptoStoreModule import org.matrix.android.sdk.internal.database.RealmKeysUtils import org.matrix.android.sdk.internal.legacy.riot.LoginStorage -import org.matrix.android.sdk.internal.network.ssl.Fingerprint -import org.matrix.android.sdk.internal.util.md5 import timber.log.Timber import java.io.File import javax.inject.Inject diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Credentials.java b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Credentials.java index 0ca0c7db85f..bbed159e3c8 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Credentials.java +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Credentials.java @@ -21,11 +21,9 @@ import org.json.JSONException; import org.json.JSONObject; -/* - * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose - */ - /** + * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose + * * The user's credentials. */ public class Credentials { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Fingerprint.java b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Fingerprint.java index 74a3f1ac550..82541d38f64 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Fingerprint.java +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/Fingerprint.java @@ -23,11 +23,9 @@ import java.util.Arrays; -/* - * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose - */ - /** + * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose + * * Represents a X509 Certificate fingerprint. */ public class Fingerprint { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/HomeServerConnectionConfig.java b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/HomeServerConnectionConfig.java index 75fc187c458..a1b46f6c094 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/HomeServerConnectionConfig.java +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/HomeServerConnectionConfig.java @@ -35,11 +35,9 @@ import okhttp3.TlsVersion; import timber.log.Timber; -/* - * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose - */ - /** + * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose + * * Represents how to connect to a specific Homeserver, may include credentials to use. */ public class HomeServerConnectionConfig { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/LoginStorage.java b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/LoginStorage.java index 62f90f563ef..924bd461ed5 100755 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/LoginStorage.java +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/LoginStorage.java @@ -29,11 +29,9 @@ import timber.log.Timber; -/* - * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose - */ - /** + * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose + * * Stores login credentials in SharedPreferences. */ public class LoginStorage { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt index 17fd0925f88..3b4bd1b1a3e 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnown.kt @@ -18,11 +18,9 @@ package org.matrix.android.sdk.internal.legacy.riot import com.squareup.moshi.Json import com.squareup.moshi.JsonClass -/* - * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose - */ - /** + * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose + * * https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery *
  * {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownBaseConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownBaseConfig.kt
index 7bbdda5eaaa..2a4ae295fdf 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownBaseConfig.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownBaseConfig.kt
@@ -18,11 +18,9 @@ package org.matrix.android.sdk.internal.legacy.riot
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
-/*
- * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
- */
-
 /**
+ * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
+ *
  * https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
  * 
  * {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownManagerConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownManagerConfig.kt
index 4efb52d61c3..6b1c67f7cbe 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownManagerConfig.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownManagerConfig.kt
@@ -15,10 +15,9 @@
  */
 package org.matrix.android.sdk.internal.legacy.riot
 
-/*
- * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
+/**
+ * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
  */
-
 data class WellKnownManagerConfig(
         val apiUrl: String,
         val uiUrl: String
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownPreferredConfig.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownPreferredConfig.kt
index feefdf920d5..beb95a1d6f6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownPreferredConfig.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/legacy/riot/WellKnownPreferredConfig.kt
@@ -18,11 +18,9 @@ package org.matrix.android.sdk.internal.legacy.riot
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
-/*
- * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
- */
-
 /**
+ * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
+ *
  * https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
  * 
  * {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/HttpHeaders.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/HttpHeaders.kt
index 26bdd905078..402e956caa4 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/HttpHeaders.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/HttpHeaders.kt
@@ -16,7 +16,7 @@
 
 package org.matrix.android.sdk.internal.network
 
-object HttpHeaders {
+internal object HttpHeaders {
 
     const val Authorization = "Authorization"
     const val UserAgent = "User-Agent"
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt
index e32f6be6fcb..cd7c99b8f96 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/NetworkConnectivityChecker.kt
@@ -25,7 +25,7 @@ import java.util.Collections
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 
-interface NetworkConnectivityChecker {
+internal interface NetworkConnectivityChecker {
     /**
      * Returns true when internet is available
      */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UnitConverterFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UnitConverterFactory.kt
index 513d8c5c861..f2571ab73fa 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UnitConverterFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/UnitConverterFactory.kt
@@ -21,7 +21,7 @@ import retrofit2.Converter
 import retrofit2.Retrofit
 import java.lang.reflect.Type
 
-object UnitConverterFactory : Converter.Factory() {
+internal object UnitConverterFactory : Converter.Factory() {
     override fun responseBodyConverter(type: Type, annotations: Array,
                                        retrofit: Retrofit): Converter? {
         return if (type == Unit::class.java) UnitConverter else null
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt
index 27684bbf1af..6efa347d3ac 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/CheckNumberType.kt
@@ -28,7 +28,7 @@ import java.math.BigDecimal
 /**
  * This is used to check if NUMBER in json is integer or double, so we can preserve typing when serializing/deserializing in a row.
  */
-interface CheckNumberType {
+internal interface CheckNumberType {
 
     companion object {
         val JSON_ADAPTER_FACTORY = object : JsonAdapter.Factory {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/ForceToBoolean.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/ForceToBoolean.kt
index f3b4cff34cd..628486bb5fa 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/ForceToBoolean.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/ForceToBoolean.kt
@@ -25,7 +25,7 @@ import timber.log.Timber
 @JsonQualifier
 @Retention(AnnotationRetention.RUNTIME)
 @Target(AnnotationTarget.FIELD, AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FUNCTION)
-annotation class ForceToBoolean
+internal annotation class ForceToBoolean
 
 internal class ForceToBooleanJsonAdapter {
     @ToJson
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.java b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.java
deleted file mode 100644
index c9bf6cc662d..00000000000
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2020 The Matrix.org Foundation C.I.C.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.matrix.android.sdk.internal.network.parsing;
-
-import com.squareup.moshi.JsonAdapter;
-import com.squareup.moshi.JsonDataException;
-import com.squareup.moshi.JsonReader;
-import com.squareup.moshi.JsonWriter;
-import com.squareup.moshi.Moshi;
-import com.squareup.moshi.Types;
-
-import java.io.IOException;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.CheckReturnValue;
-
-/**
- * A JsonAdapter factory for polymorphic types. This is useful when the type is not known before
- * decoding the JSON. This factory's adapters expect JSON in the format of a JSON object with a
- * key whose value is a label that determines the type to which to map the JSON object.
- */
-public final class RuntimeJsonAdapterFactory implements JsonAdapter.Factory {
-    final Class baseType;
-    final String labelKey;
-    final Class fallbackType;
-    final Map labelToType = new LinkedHashMap<>();
-
-    /**
-     * @param baseType The base type for which this factory will create adapters. Cannot be Object.
-     * @param labelKey The key in the JSON object whose value determines the type to which to map the
-     *                 JSON object.
-     */
-    @CheckReturnValue
-    public static  RuntimeJsonAdapterFactory of(Class baseType, String labelKey, Class fallbackType) {
-        if (baseType == null) throw new NullPointerException("baseType == null");
-        if (labelKey == null) throw new NullPointerException("labelKey == null");
-        if (baseType == Object.class) {
-            throw new IllegalArgumentException(
-                    "The base type must not be Object. Consider using a marker interface.");
-        }
-        return new RuntimeJsonAdapterFactory<>(baseType, labelKey, fallbackType);
-    }
-
-    RuntimeJsonAdapterFactory(Class baseType, String labelKey, Class fallbackType) {
-        this.baseType = baseType;
-        this.labelKey = labelKey;
-        this.fallbackType = fallbackType;
-    }
-
-    /**
-     * Register the subtype that can be created based on the label. When an unknown type is found
-     * during encoding an {@linkplain IllegalArgumentException} will be thrown. When an unknown label
-     * is found during decoding a {@linkplain JsonDataException} will be thrown.
-     */
-    public RuntimeJsonAdapterFactory registerSubtype(Class subtype, String label) {
-        if (subtype == null) throw new NullPointerException("subtype == null");
-        if (label == null) throw new NullPointerException("label == null");
-        if (labelToType.containsKey(label) || labelToType.containsValue(subtype)) {
-            throw new IllegalArgumentException("Subtypes and labels must be unique.");
-        }
-        labelToType.put(label, subtype);
-        return this;
-    }
-
-    @Override
-    public JsonAdapter create(Type type, Set annotations, Moshi moshi) {
-        if (Types.getRawType(type) != baseType || !annotations.isEmpty()) {
-            return null;
-        }
-        int size = labelToType.size();
-        Map> labelToAdapter = new LinkedHashMap<>(size);
-        Map typeToLabel = new LinkedHashMap<>(size);
-        for (Map.Entry entry : labelToType.entrySet()) {
-            String label = entry.getKey();
-            Type typeValue = entry.getValue();
-            typeToLabel.put(typeValue, label);
-            labelToAdapter.put(label, moshi.adapter(typeValue));
-        }
-
-        final JsonAdapter fallbackAdapter = moshi.adapter(fallbackType);
-        JsonAdapter objectJsonAdapter = moshi.adapter(Object.class);
-
-        return new RuntimeJsonAdapter(labelKey, labelToAdapter, typeToLabel,
-                objectJsonAdapter, fallbackAdapter).nullSafe();
-    }
-
-    static final class RuntimeJsonAdapter extends JsonAdapter {
-        final String labelKey;
-        final Map> labelToAdapter;
-        final Map typeToLabel;
-        final JsonAdapter objectJsonAdapter;
-        final JsonAdapter fallbackAdapter;
-
-        RuntimeJsonAdapter(String labelKey, Map> labelToAdapter,
-                           Map typeToLabel, JsonAdapter objectJsonAdapter,
-                           JsonAdapter fallbackAdapter) {
-            this.labelKey = labelKey;
-            this.labelToAdapter = labelToAdapter;
-            this.typeToLabel = typeToLabel;
-            this.objectJsonAdapter = objectJsonAdapter;
-            this.fallbackAdapter = fallbackAdapter;
-        }
-
-        @Override
-        public Object fromJson(JsonReader reader) throws IOException {
-            JsonReader.Token peekedToken = reader.peek();
-            if (peekedToken != JsonReader.Token.BEGIN_OBJECT) {
-                throw new JsonDataException("Expected BEGIN_OBJECT but was " + peekedToken
-                        + " at path " + reader.getPath());
-            }
-            Object jsonValue = reader.readJsonValue();
-            Map jsonObject = (Map) jsonValue;
-            Object label = jsonObject.get(labelKey);
-            if (!(label instanceof String)) {
-                return null;
-            }
-            JsonAdapter adapter = labelToAdapter.get(label);
-            if (adapter == null) {
-                return fallbackAdapter.fromJsonValue(jsonValue);
-            }
-            return adapter.fromJsonValue(jsonValue);
-        }
-
-        @Override
-        public void toJson(JsonWriter writer, Object value) throws IOException {
-            Class type = value.getClass();
-            String label = typeToLabel.get(type);
-            if (label == null) {
-                throw new IllegalArgumentException("Expected one of "
-                        + typeToLabel.keySet()
-                        + " but found "
-                        + value
-                        + ", a "
-                        + value.getClass()
-                        + ". Register this subtype.");
-            }
-            JsonAdapter adapter = labelToAdapter.get(label);
-            Map jsonValue = (Map) adapter.toJsonValue(value);
-
-            Map valueWithLabel = new LinkedHashMap<>(1 + jsonValue.size());
-            valueWithLabel.put(labelKey, label);
-            valueWithLabel.putAll(jsonValue);
-            objectJsonAdapter.toJson(writer, valueWithLabel);
-        }
-
-        @Override
-        public String toString() {
-            return "RuntimeJsonAdapter(" + labelKey + ")";
-        }
-    }
-}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt
new file mode 100644
index 00000000000..0aaa4991cde
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/parsing/RuntimeJsonAdapterFactory.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2020 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.matrix.android.sdk.internal.network.parsing
+
+import com.squareup.moshi.JsonAdapter
+import com.squareup.moshi.JsonDataException
+import com.squareup.moshi.JsonReader
+import com.squareup.moshi.JsonWriter
+import com.squareup.moshi.Moshi
+import com.squareup.moshi.Types
+import java.io.IOException
+import java.lang.reflect.Type
+import javax.annotation.CheckReturnValue
+
+/**
+ * A JsonAdapter factory for polymorphic types. This is useful when the type is not known before
+ * decoding the JSON. This factory's adapters expect JSON in the format of a JSON object with a
+ * key whose value is a label that determines the type to which to map the JSON object.
+ */
+internal class RuntimeJsonAdapterFactory(
+        private val baseType: Class,
+        private val labelKey: String,
+        private val fallbackType: Class<*>
+) : JsonAdapter.Factory {
+    private val labelToType: MutableMap = LinkedHashMap()
+
+    /**
+     * Register the subtype that can be created based on the label. When an unknown type is found
+     * during encoding an [IllegalArgumentException] will be thrown. When an unknown label
+     * is found during decoding a [JsonDataException] will be thrown.
+     */
+    fun registerSubtype(subtype: Class?, label: String?): RuntimeJsonAdapterFactory {
+        if (subtype == null) throw NullPointerException("subtype == null")
+        if (label == null) throw NullPointerException("label == null")
+        require(!(labelToType.containsKey(label) || labelToType.containsValue(subtype))) { "Subtypes and labels must be unique." }
+        labelToType[label] = subtype
+        return this
+    }
+
+    override fun create(type: Type, annotations: Set, moshi: Moshi): JsonAdapter<*>? {
+        if (Types.getRawType(type) != baseType || !annotations.isEmpty()) {
+            return null
+        }
+        val size = labelToType.size
+        val labelToAdapter: MutableMap> = LinkedHashMap(size)
+        val typeToLabel: MutableMap = LinkedHashMap(size)
+        for ((label, typeValue) in labelToType) {
+            typeToLabel[typeValue] = label
+            labelToAdapter[label] = moshi.adapter(typeValue)
+        }
+        val fallbackAdapter = moshi.adapter(fallbackType)
+        val objectJsonAdapter = moshi.adapter(Any::class.java)
+        return RuntimeJsonAdapter(labelKey, labelToAdapter, typeToLabel,
+                objectJsonAdapter, fallbackAdapter).nullSafe()
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    internal class RuntimeJsonAdapter(val labelKey: String,
+                                      val labelToAdapter: Map>,
+                                      val typeToLabel: Map,
+                                      val objectJsonAdapter: JsonAdapter,
+                                      val fallbackAdapter: JsonAdapter) : JsonAdapter() {
+        @Throws(IOException::class)
+        override fun fromJson(reader: JsonReader): Any? {
+            val peekedToken = reader.peek()
+            if (peekedToken != JsonReader.Token.BEGIN_OBJECT) {
+                throw JsonDataException("Expected BEGIN_OBJECT but was " + peekedToken +
+                        " at path " + reader.path)
+            }
+            val jsonValue = reader.readJsonValue()
+            val jsonObject = jsonValue as Map?
+            val label = jsonObject!![labelKey] as? String ?: return null
+            val adapter = labelToAdapter[label] ?: return fallbackAdapter.fromJsonValue(jsonValue)
+            return adapter.fromJsonValue(jsonValue)
+        }
+
+        @Throws(IOException::class)
+        override fun toJson(writer: JsonWriter, value: Any?) {
+            val type: Class<*> = value!!.javaClass
+            val label = typeToLabel[type]
+                    ?: throw IllegalArgumentException("Expected one of " +
+                            typeToLabel.keys +
+                            " but found " +
+                            value +
+                            ", a " +
+                            value.javaClass +
+                            ". Register this subtype.")
+            val adapter = labelToAdapter[label]!!
+            val jsonValue = adapter.toJsonValue(value) as Map?
+            val valueWithLabel: MutableMap = LinkedHashMap(1 + jsonValue!!.size)
+            valueWithLabel[labelKey] = label
+            valueWithLabel.putAll(jsonValue)
+            objectJsonAdapter.toJson(writer, valueWithLabel)
+        }
+
+        override fun toString(): String {
+            return "RuntimeJsonAdapter($labelKey)"
+        }
+    }
+
+    companion object {
+        /**
+         * @param baseType The base type for which this factory will create adapters. Cannot be Object.
+         * @param labelKey The key in the JSON object whose value determines the type to which to map the
+         * JSON object.
+         */
+        @CheckReturnValue
+        fun  of(baseType: Class, labelKey: String, fallbackType: Class): RuntimeJsonAdapterFactory {
+            require(baseType != Any::class.java) { "The base type must not be Object. Consider using a marker interface." }
+            return RuntimeJsonAdapterFactory(baseType, labelKey, fallbackType)
+        }
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManager.kt
index 6f245aa6d8d..ccae5ad14f9 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManager.kt
@@ -16,6 +16,7 @@
 
 package org.matrix.android.sdk.internal.network.ssl
 
+import org.matrix.android.sdk.api.network.ssl.Fingerprint
 import java.security.cert.CertificateException
 import java.security.cert.X509Certificate
 import javax.net.ssl.X509TrustManager
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerApi24.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerApi24.kt
index 4e58a0f2e5a..574f1ef81db 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerApi24.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerApi24.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.network.ssl
 
 import android.os.Build
 import androidx.annotation.RequiresApi
+import org.matrix.android.sdk.api.network.ssl.Fingerprint
 import java.net.Socket
 import java.security.cert.CertificateException
 import java.security.cert.X509Certificate
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerProvider.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerProvider.kt
index 57b97c75c50..f01ee7af24f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerProvider.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/PinnedTrustManagerProvider.kt
@@ -17,6 +17,7 @@
 package org.matrix.android.sdk.internal.network.ssl
 
 import android.os.Build
+import org.matrix.android.sdk.api.network.ssl.Fingerprint
 import javax.net.ssl.X509ExtendedTrustManager
 import javax.net.ssl.X509TrustManager
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/UnrecognizedCertificateException.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/UnrecognizedCertificateException.kt
index ca841f0ffb9..62eb6cf1f64 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/UnrecognizedCertificateException.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/network/ssl/UnrecognizedCertificateException.kt
@@ -16,6 +16,7 @@
 
 package org.matrix.android.sdk.internal.network.ssl
 
+import org.matrix.android.sdk.api.network.ssl.Fingerprint
 import java.security.cert.CertificateException
 import java.security.cert.X509Certificate
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryEnumListProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryEnumListProcessor.kt
index 5653d7171dd..b4415afcbcc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryEnumListProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryEnumListProcessor.kt
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.query
 import io.realm.RealmObject
 import io.realm.RealmQuery
 
-fun > RealmQuery.process(field: String, enums: List>): RealmQuery {
+internal fun > RealmQuery.process(field: String, enums: List>): RealmQuery {
     val lastEnumValue = enums.lastOrNull()
     beginGroup()
     for (enumValue in enums) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt
index b42bf2b8c78..ba4d05e747a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/query/QueryStringValueProcessor.kt
@@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.query.QueryStringValue.ContentQueryStringValue
 import org.matrix.android.sdk.internal.util.Normalizer
 import javax.inject.Inject
 
-class QueryStringValueProcessor @Inject constructor(
+internal class QueryStringValueProcessor @Inject constructor(
         private val normalizer: Normalizer
 ) {
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/migration/MigrateGlobalTo001.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/migration/MigrateGlobalTo001.kt
index cff2f7b8e86..7b332573684 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/migration/MigrateGlobalTo001.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/raw/migration/MigrateGlobalTo001.kt
@@ -20,7 +20,7 @@ import io.realm.DynamicRealm
 import org.matrix.android.sdk.internal.database.model.KnownServerUrlEntityFields
 import org.matrix.android.sdk.internal.util.database.RealmMigrator
 
-class MigrateGlobalTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
+internal class MigrateGlobalTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
 
     override fun doMigrate(realm: DynamicRealm) {
         realm.schema.create("KnownServerUrlEntity")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
index 08651764c2f..ac097f57ee6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultFileService.kt
@@ -30,14 +30,14 @@ import okhttp3.RequestBody.Companion.toRequestBody
 import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
 import org.matrix.android.sdk.api.failure.Failure
 import org.matrix.android.sdk.api.session.content.ContentUrlResolver
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.api.session.file.FileService
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.util.md5
 import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
 import org.matrix.android.sdk.internal.di.SessionDownloadsDirectory
 import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificateWithProgress
 import org.matrix.android.sdk.internal.session.download.DownloadProgressInterceptor.Companion.DOWNLOAD_PROGRESS_INTERCEPTOR_HEADER
 import org.matrix.android.sdk.internal.util.file.AtomicFileCreator
-import org.matrix.android.sdk.internal.util.md5
 import org.matrix.android.sdk.internal.util.writeToFile
 import timber.log.Timber
 import java.io.File
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt
index 1615b8eef9a..609acdd89c3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/DefaultToDeviceService.kt
@@ -17,10 +17,10 @@
 package org.matrix.android.sdk.internal.session
 
 import org.matrix.android.sdk.api.session.ToDeviceService
+import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
 import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.internal.crypto.actions.MessageEncrypter
-import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
 import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
 import org.matrix.android.sdk.internal.crypto.tasks.SendToDeviceTask
 import javax.inject.Inject
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
index 531dea1d5a6..0aae9f31058 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/SessionModule.kt
@@ -45,6 +45,7 @@ import org.matrix.android.sdk.api.session.permalinks.PermalinkService
 import org.matrix.android.sdk.api.session.securestorage.SecureStorageService
 import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
 import org.matrix.android.sdk.api.session.typing.TypingUsersTracker
+import org.matrix.android.sdk.api.util.md5
 import org.matrix.android.sdk.internal.crypto.secrets.DefaultSharedSecretStorageService
 import org.matrix.android.sdk.internal.crypto.tasks.DefaultRedactEventTask
 import org.matrix.android.sdk.internal.crypto.tasks.RedactEventTask
@@ -87,6 +88,8 @@ import org.matrix.android.sdk.internal.session.integrationmanager.IntegrationMan
 import org.matrix.android.sdk.internal.session.openid.DefaultOpenIdService
 import org.matrix.android.sdk.internal.session.permalinks.DefaultPermalinkService
 import org.matrix.android.sdk.internal.session.room.EventRelationsAggregationProcessor
+import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.DefaultLiveLocationAggregationProcessor
+import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
 import org.matrix.android.sdk.internal.session.room.create.RoomCreateEventProcessor
 import org.matrix.android.sdk.internal.session.room.prune.RedactionEventProcessor
 import org.matrix.android.sdk.internal.session.room.send.queue.EventSenderProcessor
@@ -96,7 +99,6 @@ import org.matrix.android.sdk.internal.session.securestorage.DefaultSecureStorag
 import org.matrix.android.sdk.internal.session.typing.DefaultTypingUsersTracker
 import org.matrix.android.sdk.internal.session.user.accountdata.DefaultSessionAccountDataService
 import org.matrix.android.sdk.internal.session.widgets.DefaultWidgetURLFormatter
-import org.matrix.android.sdk.internal.util.md5
 import retrofit2.Retrofit
 import java.io.File
 import javax.inject.Provider
@@ -104,7 +106,7 @@ import javax.inject.Qualifier
 
 @Qualifier
 @Retention(AnnotationRetention.RUNTIME)
-annotation class MockHttpInterceptor
+internal annotation class MockHttpInterceptor
 
 @Module
 internal abstract class SessionModule {
@@ -390,4 +392,7 @@ internal abstract class SessionModule {
 
     @Binds
     abstract fun bindEventSenderProcessor(processor: EventSenderProcessorCoroutine): EventSenderProcessor
+
+    @Binds
+    abstract fun bindLiveLocationAggregationProcessor(processor: DefaultLiveLocationAggregationProcessor): LiveLocationAggregationProcessor
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/StreamEventsManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/StreamEventsManager.kt
index bb0ca114454..cfc26045a0e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/StreamEventsManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/StreamEventsManager.kt
@@ -22,8 +22,8 @@ import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.LiveEventListener
+import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Event
-import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -71,7 +71,7 @@ internal class StreamEventsManager @Inject constructor() {
         coroutineScope.launch {
             listeners.forEach {
                 tryOrNull {
-                    it.onEventDecrypted(event.eventId ?: "", event.roomId ?: "", result.clearEvent)
+                    it.onEventDecrypted(event, result.clearEvent)
                 }
             }
         }
@@ -82,7 +82,7 @@ internal class StreamEventsManager @Inject constructor() {
         coroutineScope.launch {
             listeners.forEach {
                 tryOrNull {
-                    it.onEventDecryptionError(event.eventId ?: "", event.roomId ?: "", error)
+                    it.onEventDecryptionError(event, error)
                 }
             }
         }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/TestInterceptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/TestInterceptor.kt
index fad68afd8aa..5b2ba91ba29 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/TestInterceptor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/TestInterceptor.kt
@@ -18,6 +18,6 @@ package org.matrix.android.sdk.internal.session
 
 import okhttp3.Interceptor
 
-interface TestInterceptor : Interceptor {
+internal interface TestInterceptor : Interceptor {
     var sessionId: String?
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt
index 660ab8726f7..5d774244823 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/DefaultContentUrlResolver.kt
@@ -21,7 +21,7 @@ import org.matrix.android.sdk.api.MatrixUrls.removeMxcPrefix
 import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig
 import org.matrix.android.sdk.api.session.content.ContentUrlResolver
 import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.internal.network.NetworkConstants
 import org.matrix.android.sdk.internal.session.contentscanner.ScanEncryptorUtils
 import org.matrix.android.sdk.internal.session.contentscanner.model.toJson
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
index 52dee0ee55c..75606f2e7a7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/content/UploadContentWorker.kt
@@ -25,6 +25,7 @@ import com.squareup.moshi.JsonClass
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.listeners.ProgressListener
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
+import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo
 import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
@@ -35,7 +36,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
 import org.matrix.android.sdk.api.util.MimeTypes
 import org.matrix.android.sdk.internal.SessionManager
 import org.matrix.android.sdk.internal.crypto.attachments.MXEncryptedAttachments
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
 import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.network.ProgressRequestBody
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt
index 4ecb3376033..da7e2d102e0 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DefaultContentScannerService.kt
@@ -23,8 +23,8 @@ import okhttp3.OkHttpClient
 import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
 import org.matrix.android.sdk.api.session.contentscanner.ScanState
 import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.api.util.Optional
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.internal.di.Unauthenticated
 import org.matrix.android.sdk.internal.network.RetrofitFactory
 import org.matrix.android.sdk.internal.session.SessionScope
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DisabledContentScannerService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DisabledContentScannerService.kt
index 9087c715663..41c444ad837 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DisabledContentScannerService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/DisabledContentScannerService.kt
@@ -20,8 +20,8 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.MutableLiveData
 import org.matrix.android.sdk.api.session.contentscanner.ContentScannerService
 import org.matrix.android.sdk.api.session.contentscanner.ScanStatusInfo
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.api.util.Optional
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.internal.session.SessionScope
 import javax.inject.Inject
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/ScanEncryptorUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/ScanEncryptorUtils.kt
index 8fc84a487e5..7d14e4ed800 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/ScanEncryptorUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/ScanEncryptorUtils.kt
@@ -16,9 +16,9 @@
 
 package org.matrix.android.sdk.internal.session.contentscanner
 
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileKey
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo
+import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileKey
 import org.matrix.android.sdk.internal.crypto.tools.withOlmEncryption
 import org.matrix.android.sdk.internal.session.contentscanner.model.DownloadBody
 import org.matrix.android.sdk.internal.session.contentscanner.model.EncryptedBody
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/DownloadBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/DownloadBody.kt
index 5bac96a0c0e..5ffb4e79832 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/DownloadBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/model/DownloadBody.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.contentscanner.model
 
 import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
-import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
+import org.matrix.android.sdk.api.session.crypto.model.EncryptedFileInfo
 import org.matrix.android.sdk.internal.di.MoshiProvider
 import org.matrix.android.sdk.internal.util.JsonCanonicalizer
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/DownloadEncryptedTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/DownloadEncryptedTask.kt
index f92c869cb89..abde84b6afc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/DownloadEncryptedTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/DownloadEncryptedTask.kt
@@ -17,7 +17,7 @@
 package org.matrix.android.sdk.internal.session.contentscanner.tasks
 
 import okhttp3.ResponseBody
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.internal.network.executeRequest
 import org.matrix.android.sdk.internal.session.contentscanner.ContentScannerApiProvider
 import org.matrix.android.sdk.internal.session.contentscanner.ScanEncryptorUtils
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/ScanEncryptedTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/ScanEncryptedTask.kt
index dab9b5538fe..e098607eb6c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/ScanEncryptedTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/contentscanner/tasks/ScanEncryptedTask.kt
@@ -18,7 +18,7 @@ package org.matrix.android.sdk.internal.session.contentscanner.tasks
 
 import org.matrix.android.sdk.api.failure.toScanFailure
 import org.matrix.android.sdk.api.session.contentscanner.ScanState
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 import org.matrix.android.sdk.internal.network.executeRequest
 import org.matrix.android.sdk.internal.session.contentscanner.ContentScannerApiProvider
 import org.matrix.android.sdk.internal.session.contentscanner.ScanEncryptorUtils
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt
index 19bc7e1908b..16c57baafc5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/directory/DirectoryAPI.kt
@@ -16,9 +16,9 @@
 
 package org.matrix.android.sdk.internal.session.directory
 
+import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
 import org.matrix.android.sdk.internal.network.NetworkConstants
 import org.matrix.android.sdk.internal.session.room.alias.AddRoomAliasBody
-import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
 import retrofit2.http.Body
 import retrofit2.http.DELETE
 import retrofit2.http.GET
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/ProgressResponseBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/ProgressResponseBody.kt
index f4cb1a80e58..4fd4fda7d1a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/ProgressResponseBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/download/ProgressResponseBody.kt
@@ -24,7 +24,7 @@ import okio.ForwardingSource
 import okio.Source
 import okio.buffer
 
-class ProgressResponseBody(
+internal class ProgressResponseBody(
         private val responseBody: ResponseBody,
         private val chainUrl: String,
         private val progressListener: ProgressListener) : ResponseBody() {
@@ -56,7 +56,7 @@ class ProgressResponseBody(
     }
 }
 
-interface ProgressListener {
+internal interface ProgressListener {
     fun update(url: String, bytesRead: Long, contentLength: Long, done: Boolean)
     fun error(url: String, errorCode: Int)
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/EventFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/EventFilter.kt
index 37630ef8bad..27a12a61453 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/EventFilter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/EventFilter.kt
@@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass
  * https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-user-userid-filter
  */
 @JsonClass(generateAdapter = true)
-data class EventFilter(
+internal data class EventFilter(
         /**
          * The maximum number of events to return.
          */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterResponse.kt
index b2d54292163..3719c803ccb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/FilterResponse.kt
@@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass
  * https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-user-userid-filter
  */
 @JsonClass(generateAdapter = true)
-data class FilterResponse(
+internal data class FilterResponse(
         /**
          * Required. The ID of the filter that was created. Cannot start with a { as this character
          * is used to determine if the filter provided is inline JSON or a previously declared
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomEventFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomEventFilter.kt
index 634ea73480a..220c4011375 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomEventFilter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomEventFilter.kt
@@ -24,7 +24,7 @@ import org.matrix.android.sdk.internal.di.MoshiProvider
  * https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-user-userid-filter
  */
 @JsonClass(generateAdapter = true)
-data class RoomEventFilter(
+internal data class RoomEventFilter(
         /**
          * The maximum number of events to return.
          */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt
index 2c56a30d394..585d013eaef 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/filter/RoomFilter.kt
@@ -23,7 +23,7 @@ import com.squareup.moshi.JsonClass
  * https://matrix.org/docs/spec/client_server/r0.3.0.html#post-matrix-client-r0-user-userid-filter
  */
 @JsonClass(generateAdapter = true)
-data class RoomFilter(
+internal data class RoomFilter(
         /**
          * A list of room IDs to exclude. If this list is absent then no rooms are excluded.
          * A matching room will be excluded even if it is listed in the 'rooms' filter.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt
index c8a9c0f09ad..4285f38893c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/DefaultIdentityService.kt
@@ -39,13 +39,13 @@ import org.matrix.android.sdk.api.session.identity.IdentityServiceError
 import org.matrix.android.sdk.api.session.identity.IdentityServiceListener
 import org.matrix.android.sdk.api.session.identity.SharedState
 import org.matrix.android.sdk.api.session.identity.ThreePid
+import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.di.AuthenticatedIdentity
 import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
 import org.matrix.android.sdk.internal.extensions.observeNotNull
 import org.matrix.android.sdk.internal.network.RetrofitFactory
 import org.matrix.android.sdk.internal.session.SessionScope
 import org.matrix.android.sdk.internal.session.identity.data.IdentityStore
-import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.session.openid.GetOpenIdTokenTask
 import org.matrix.android.sdk.internal.session.profile.BindThreePidsTask
 import org.matrix.android.sdk.internal.session.profile.UnbindThreePidsTask
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt
index 99bd740463f..7ca87586770 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/IdentityAPI.kt
@@ -16,6 +16,7 @@
 
 package org.matrix.android.sdk.internal.session.identity
 
+import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.auth.registration.SuccessResult
 import org.matrix.android.sdk.internal.network.NetworkConstants
 import org.matrix.android.sdk.internal.session.identity.model.IdentityAccountResponse
@@ -26,7 +27,6 @@ import org.matrix.android.sdk.internal.session.identity.model.IdentityRequestOwn
 import org.matrix.android.sdk.internal.session.identity.model.IdentityRequestTokenForEmailBody
 import org.matrix.android.sdk.internal.session.identity.model.IdentityRequestTokenForMsisdnBody
 import org.matrix.android.sdk.internal.session.identity.model.IdentityRequestTokenResponse
-import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult
 import retrofit2.http.Body
 import retrofit2.http.GET
 import retrofit2.http.POST
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/Sign3pidInvitationTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/Sign3pidInvitationTask.kt
index d491af33cad..06a6cecc05d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/Sign3pidInvitationTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/Sign3pidInvitationTask.kt
@@ -18,10 +18,10 @@ package org.matrix.android.sdk.internal.session.identity
 
 import dagger.Lazy
 import okhttp3.OkHttpClient
+import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.di.Unauthenticated
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.network.RetrofitFactory
-import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.task.Task
 import javax.inject.Inject
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/migration/MigrateIdentityTo001.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/migration/MigrateIdentityTo001.kt
index 002601470d8..17a23b828ad 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/migration/MigrateIdentityTo001.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/identity/db/migration/MigrateIdentityTo001.kt
@@ -21,7 +21,7 @@ import org.matrix.android.sdk.internal.session.identity.db.IdentityDataEntityFie
 import org.matrix.android.sdk.internal.util.database.RealmMigrator
 import timber.log.Timber
 
-class MigrateIdentityTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
+internal class MigrateIdentityTo001(realm: DynamicRealm) : RealmMigrator(realm, 1) {
 
     override fun doMigrate(realm: DynamicRealm) {
         Timber.d("Add field userConsent (Boolean) and set the value to false")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt
index 079b0d0115e..4a1e6661b0c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/initsync/DefaultSyncStatusService.kt
@@ -72,7 +72,7 @@ internal class DefaultSyncStatusService @Inject constructor() :
                 // Update the progress of the leaf and all its parents
                 leaf.setProgress(progress)
                 // Then update the live data using leaf wording and root progress
-                status.postValue(SyncStatusService.Status.Progressing(leaf.initSyncStep, root.currentProgress.toInt()))
+                status.postValue(SyncStatusService.Status.InitialSyncProgressing(leaf.initSyncStep, root.currentProgress.toInt()))
             }
         }
     }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
index 8ae203c2b31..899bce4c8dd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/notification/ProcessEventForPushTask.kt
@@ -57,6 +57,7 @@ internal class DefaultProcessEventForPushTask @Inject constructor(
         val allEvents = (newJoinEvents + inviteEvents).filter { event ->
             when (event.type) {
                 in EventType.POLL_START,
+                in EventType.STATE_ROOM_BEACON_INFO,
                 EventType.MESSAGE,
                 EventType.REDACTION,
                 EventType.ENCRYPTED,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/GetPresenceResponse.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/GetPresenceResponse.kt
index a7552f7b027..1cd6d7d3f20 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/GetPresenceResponse.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/GetPresenceResponse.kt
@@ -21,7 +21,7 @@ import com.squareup.moshi.JsonClass
 import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
 
 @JsonClass(generateAdapter = true)
-data class GetPresenceResponse(
+internal data class GetPresenceResponse(
         @Json(name = "presence")
         val presence: PresenceEnum,
         @Json(name = "last_active_ago")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt
index 45e0fcf06ef..b1ca5126528 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/model/PresenceContent.kt
@@ -24,7 +24,7 @@ import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
  * Class representing the EventType.PRESENCE event content
  */
 @JsonClass(generateAdapter = true)
-data class PresenceContent(
+internal data class PresenceContent(
         /**
          * Required. The presence state for this user. One of: ["online", "offline", "unavailable"]
          */
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/service/DefaultPresenceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/service/DefaultPresenceService.kt
index 1083d5b4c2e..ca89ef684f5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/service/DefaultPresenceService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/presence/service/DefaultPresenceService.kt
@@ -23,15 +23,19 @@ import org.matrix.android.sdk.api.session.presence.model.UserPresence
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.presence.service.task.GetPresenceTask
 import org.matrix.android.sdk.internal.session.presence.service.task.SetPresenceTask
+import org.matrix.android.sdk.internal.session.sync.SyncPresence
+import org.matrix.android.sdk.internal.settings.DefaultLightweightSettingsStorage
 import javax.inject.Inject
 
 internal class DefaultPresenceService @Inject constructor(
         @UserId private val userId: String,
         private val setPresenceTask: SetPresenceTask,
-        private val getPresenceTask: GetPresenceTask
+        private val getPresenceTask: GetPresenceTask,
+        private val lightweightSettingsStorage: DefaultLightweightSettingsStorage
 ) : PresenceService {
 
     override suspend fun setMyPresence(presence: PresenceEnum, statusMsg: String?) {
+        lightweightSettingsStorage.setSyncPresenceStatus(SyncPresence.from(presence))
         setPresenceTask.execute(SetPresenceTask.Params(userId, presence, statusMsg))
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidBody.kt
index fa45ae99402..4d2a999137e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/profile/BindThreePidBody.kt
@@ -30,17 +30,17 @@ internal data class BindThreePidBody(
          * Required. The identity server to use. (without "https://")
          */
         @Json(name = "id_server")
-        var identityServerUrlWithoutProtocol: String,
+        val identityServerUrlWithoutProtocol: String,
 
         /**
          * Required. An access token previously registered with the identity server.
          */
         @Json(name = "id_access_token")
-        var identityServerAccessToken: String,
+        val identityServerAccessToken: String,
 
         /**
          * Required. The session identifier given by the identity server.
          */
         @Json(name = "sid")
-        var sid: String
+        val sid: String
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
index 34e859e5093..3f129c4d71b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoom.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room
 
 import androidx.lifecycle.LiveData
 import org.matrix.android.sdk.api.MatrixCoroutineDispatchers
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.session.crypto.CryptoService
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.room.Room
@@ -44,13 +45,12 @@ import org.matrix.android.sdk.api.session.room.version.RoomVersionService
 import org.matrix.android.sdk.api.session.search.SearchResult
 import org.matrix.android.sdk.api.session.space.Space
 import org.matrix.android.sdk.api.util.Optional
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
+import org.matrix.android.sdk.api.util.awaitCallback
 import org.matrix.android.sdk.internal.session.permalinks.ViaParameterFinder
 import org.matrix.android.sdk.internal.session.room.state.SendStateTask
 import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
 import org.matrix.android.sdk.internal.session.search.SearchTask
 import org.matrix.android.sdk.internal.session.space.DefaultSpace
-import org.matrix.android.sdk.internal.util.awaitCallback
 import java.security.InvalidParameterException
 
 internal class DefaultRoom(override val roomId: String,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt
index c79c41069b3..8424ee8a363 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/DefaultRoomService.kt
@@ -22,11 +22,13 @@ import androidx.paging.PagedList
 import com.zhuinden.monarchy.Monarchy
 import org.matrix.android.sdk.api.query.QueryStringValue
 import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.api.session.room.Room
 import org.matrix.android.sdk.api.session.room.RoomService
 import org.matrix.android.sdk.api.session.room.RoomSortOrder
 import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
 import org.matrix.android.sdk.api.session.room.UpdatableLivePageResult
+import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
 import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
@@ -40,10 +42,8 @@ import org.matrix.android.sdk.api.util.toOptional
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.model.RoomMemberSummaryEntityFields
 import org.matrix.android.sdk.internal.di.SessionDatabase
-import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.session.room.alias.DeleteRoomAliasTask
 import org.matrix.android.sdk.internal.session.room.alias.GetRoomIdByAliasTask
-import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
 import org.matrix.android.sdk.internal.session.room.create.CreateRoomTask
 import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
 import org.matrix.android.sdk.internal.session.room.membership.RoomMemberHelper
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
index 8bbe3a9ac61..15ce5810c81 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt
@@ -16,14 +16,15 @@
 package org.matrix.android.sdk.internal.session.room
 
 import io.realm.Realm
-import org.matrix.android.sdk.api.crypto.VerificationState
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.query.QueryStringValue
+import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
 import org.matrix.android.sdk.api.session.events.model.AggregatedAnnotation
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.LocalEcho
 import org.matrix.android.sdk.api.session.events.model.RelationType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.getRelationContent
 import org.matrix.android.sdk.api.session.events.model.toContent
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -34,6 +35,7 @@ import org.matrix.android.sdk.api.session.room.model.VoteInfo
 import org.matrix.android.sdk.api.session.room.model.VoteSummary
 import org.matrix.android.sdk.api.session.room.model.message.MessageContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent
 import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
 import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
@@ -42,7 +44,6 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
 import org.matrix.android.sdk.internal.SessionManager
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
 import org.matrix.android.sdk.internal.crypto.verification.toState
 import org.matrix.android.sdk.internal.database.helper.findRootThreadEvent
 import org.matrix.android.sdk.internal.database.mapper.ContentMapper
@@ -64,6 +65,7 @@ import org.matrix.android.sdk.internal.database.query.where
 import org.matrix.android.sdk.internal.di.SessionId
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
+import org.matrix.android.sdk.internal.session.room.aggregation.livelocation.LiveLocationAggregationProcessor
 import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
 import timber.log.Timber
 import javax.inject.Inject
@@ -72,7 +74,8 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
         @UserId private val userId: String,
         private val stateEventDataSource: StateEventDataSource,
         @SessionId private val sessionId: String,
-        private val sessionManager: SessionManager
+        private val sessionManager: SessionManager,
+        private val liveLocationAggregationProcessor: LiveLocationAggregationProcessor
 ) : EventInsertLiveProcessor {
 
     private val allowedTypes = listOf(
@@ -88,7 +91,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
             // EventType.KEY_VERIFICATION_READY,
             EventType.KEY_VERIFICATION_KEY,
             EventType.ENCRYPTED
-    ) + EventType.POLL_START + EventType.POLL_RESPONSE + EventType.POLL_END
+    ) + EventType.POLL_START + EventType.POLL_RESPONSE + EventType.POLL_END + EventType.BEACON_LOCATION_DATA
 
     override fun shouldProcess(eventId: String, eventType: String, insertType: EventInsertType): Boolean {
         return allowedTypes.contains(eventType)
@@ -103,12 +106,12 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
             }
             val isLocalEcho = LocalEcho.isLocalEchoId(event.eventId ?: "")
             when (event.type) {
-                EventType.REACTION             -> {
+                EventType.REACTION                -> {
                     // we got a reaction!!
                     Timber.v("###REACTION in room $roomId , reaction eventID ${event.eventId}")
                     handleReaction(realm, event, roomId, isLocalEcho)
                 }
-                EventType.MESSAGE              -> {
+                EventType.MESSAGE                 -> {
                     if (event.unsignedData?.relations?.annotations != null) {
                         Timber.v("###REACTION Aggregation in room $roomId for event ${event.eventId}")
                         handleInitialAggregatedRelations(realm, event, roomId, event.unsignedData.relations.annotations)
@@ -134,7 +137,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                 EventType.KEY_VERIFICATION_START,
                 EventType.KEY_VERIFICATION_MAC,
                 EventType.KEY_VERIFICATION_READY,
-                EventType.KEY_VERIFICATION_KEY -> {
+                EventType.KEY_VERIFICATION_KEY    -> {
                     Timber.v("## SAS REF in room $roomId for event ${event.eventId}")
                     event.content.toModel()?.relatesTo?.let {
                         if (it.type == RelationType.REFERENCE && it.eventId != null) {
@@ -143,7 +146,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                     }
                 }
 
-                EventType.ENCRYPTED            -> {
+                EventType.ENCRYPTED               -> {
                     // Relation type is in clear
                     val encryptedEventContent = event.content.toModel()
                     if (encryptedEventContent?.relatesTo?.type == RelationType.REPLACE ||
@@ -169,22 +172,27 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                             EventType.KEY_VERIFICATION_START,
                             EventType.KEY_VERIFICATION_MAC,
                             EventType.KEY_VERIFICATION_READY,
-                            EventType.KEY_VERIFICATION_KEY -> {
+                            EventType.KEY_VERIFICATION_KEY    -> {
                                 Timber.v("## SAS REF in room $roomId for event ${event.eventId}")
                                 encryptedEventContent.relatesTo.eventId?.let {
                                     handleVerification(realm, event, roomId, isLocalEcho, it)
                                 }
                             }
-                            in EventType.POLL_RESPONSE     -> {
+                            in EventType.POLL_RESPONSE        -> {
                                 event.getClearContent().toModel(catchError = true)?.let {
                                     handleResponse(realm, event, it, roomId, isLocalEcho, event.getRelationContent()?.eventId)
                                 }
                             }
-                            in EventType.POLL_END          -> {
+                            in EventType.POLL_END             -> {
                                 event.content.toModel(catchError = true)?.let {
                                     handleEndPoll(realm, event, it, roomId, isLocalEcho)
                                 }
                             }
+                            in EventType.BEACON_LOCATION_DATA -> {
+                                event.content.toModel(catchError = true)?.let {
+                                    liveLocationAggregationProcessor.handleLiveLocation(realm, event, it, roomId, isLocalEcho)
+                                }
+                            }
                         }
                     } else if (encryptedEventContent?.relatesTo?.type == RelationType.ANNOTATION) {
                         // Reaction
@@ -205,7 +213,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
 //                                 }
 //                    }
                 }
-                EventType.REDACTION            -> {
+                EventType.REDACTION               -> {
                     val eventToPrune = event.redacts?.let { EventEntity.where(realm, eventId = it).findFirst() }
                             ?: return
                     when (eventToPrune.type) {
@@ -225,7 +233,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                         }
                     }
                 }
-                in EventType.POLL_START        -> {
+                in EventType.POLL_START           -> {
                     val content: MessagePollContent? = event.content.toModel()
                     if (content?.relatesTo?.type == RelationType.REPLACE) {
                         Timber.v("###REPLACE in room $roomId for event ${event.eventId}")
@@ -233,17 +241,22 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                         handleReplace(realm, event, content, roomId, isLocalEcho)
                     }
                 }
-                in EventType.POLL_RESPONSE     -> {
+                in EventType.POLL_RESPONSE        -> {
                     event.content.toModel(catchError = true)?.let {
                         handleResponse(realm, event, it, roomId, isLocalEcho)
                     }
                 }
-                in EventType.POLL_END          -> {
+                in EventType.POLL_END             -> {
                     event.content.toModel(catchError = true)?.let {
                         handleEndPoll(realm, event, it, roomId, isLocalEcho)
                     }
                 }
-                else                           -> Timber.v("UnHandled event ${event.eventId}")
+                in EventType.BEACON_LOCATION_DATA -> {
+                    event.content.toModel(catchError = true)?.let {
+                        liveLocationAggregationProcessor.handleLiveLocation(realm, event, it, roomId, isLocalEcho)
+                    }
+                }
+                else                              -> Timber.v("UnHandled event ${event.eventId}")
             }
         } catch (t: Throwable) {
             Timber.e(t, "## Should not happen ")
@@ -303,14 +316,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
             ContentMapper
                     .map(eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent)
                     ?.toModel()
-                    ?.apply {
-                        totalVotes = 0
-                        winnerVoteCount = 0
-                        votes = emptyList()
-                        votesSummary = emptyMap()
-                    }
-                    ?.apply {
-                        eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent = ContentMapper.map(toContent())
+                    ?.let { existingPollSummaryContent ->
+                        eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent = ContentMapper.map(
+                                PollSummaryContent(
+                                        myVote = existingPollSummaryContent.myVote,
+                                        votes = emptyList(),
+                                        votesSummary = emptyMap(),
+                                        totalVotes = 0,
+                                        winnerVoteCount = 0,
+                                )
+                                        .toContent())
                     }
 
             val txId = event.unsignedData?.transactionId
@@ -397,15 +412,15 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                     existing.pollResponseSummary = it
                 }
 
-        val closedTime = existingPollSummary?.closedTime
+        val closedTime = existingPollSummary.closedTime
         if (closedTime != null && eventTimestamp > closedTime) {
             Timber.v("## POLL is closed ignore event poll:$targetEventId, event :${event.eventId}")
             return
         }
 
-        val sumModel = ContentMapper.map(existingPollSummary?.aggregatedContent).toModel() ?: PollSummaryContent()
+        val currentModel = ContentMapper.map(existingPollSummary.aggregatedContent).toModel()
 
-        if (existingPollSummary!!.sourceEvents.contains(eventId)) {
+        if (existingPollSummary.sourceEvents.contains(eventId)) {
             // ignore this event, we already know it (??)
             Timber.v("## POLL  ignoring event for summary, it's known eventId:$eventId")
             return
@@ -430,7 +445,9 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
             return
         }
 
-        val votes = sumModel.votes?.toMutableList() ?: ArrayList()
+        val votes = currentModel?.votes.orEmpty().toMutableList()
+
+        var myVote: String? = null
         val existingVoteIndex = votes.indexOfFirst { it.userId == senderId }
         if (existingVoteIndex != -1) {
             // Is the vote newer?
@@ -439,7 +456,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                 // Take the new one
                 votes[existingVoteIndex] = VoteInfo(senderId, option, eventTimestamp)
                 if (userId == senderId) {
-                    sumModel.myVote = option
+                    myVote = option
                 }
                 Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
             } else {
@@ -448,16 +465,14 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
         } else {
             votes.add(VoteInfo(senderId, option, eventTimestamp))
             if (userId == senderId) {
-                sumModel.myVote = option
+                myVote = option
             }
             Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
         }
-        sumModel.votes = votes
 
         // Precompute the percentage of votes for all options
         val totalVotes = votes.size
-        sumModel.totalVotes = totalVotes
-        sumModel.votesSummary = votes
+        val newVotesSummary = votes
                 .groupBy({ it.option }, { it.userId })
                 .mapValues {
                     VoteSummary(
@@ -465,7 +480,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                             percentage = if (totalVotes == 0 && it.value.isEmpty()) 0.0 else it.value.size.toDouble() / totalVotes
                     )
                 }
-        sumModel.winnerVoteCount = sumModel.votesSummary?.maxOf { it.value.total } ?: 0
+        val newWinnerVoteCount = newVotesSummary.maxOf { it.value.total }
 
         if (isLocalEcho) {
             existingPollSummary.sourceLocalEchoEvents.add(eventId)
@@ -473,7 +488,15 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
             existingPollSummary.sourceEvents.add(eventId)
         }
 
-        existingPollSummary.aggregatedContent = ContentMapper.map(sumModel.toContent())
+        val newSumModel = PollSummaryContent(
+                myVote = myVote,
+                votes = votes,
+                votesSummary = newVotesSummary,
+                totalVotes = totalVotes,
+                winnerVoteCount = newWinnerVoteCount
+        )
+
+        existingPollSummary.aggregatedContent = ContentMapper.map(newSumModel.toContent())
     }
 
     private fun handleEndPoll(realm: Realm,
@@ -584,11 +607,11 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                 sum.key = reaction
                 sum.firstTimestamp = event.originServerTs ?: 0
                 if (isLocalEcho) {
-                    Timber.v("Adding local echo reaction $reaction")
+                    Timber.v("Adding local echo reaction")
                     sum.sourceLocalEcho.add(txId)
                     sum.count = 1
                 } else {
-                    Timber.v("Adding synced reaction $reaction")
+                    Timber.v("Adding synced reaction")
                     sum.count = 1
                     sum.sourceEvents.add(reactionEventId)
                 }
@@ -600,16 +623,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
                     // check if it's not the sync of a local echo
                     if (!isLocalEcho && sum.sourceLocalEcho.contains(txId)) {
                         // ok it has already been counted, just sync the list, do not touch count
-                        Timber.v("Ignoring synced of local echo for reaction $reaction")
+                        Timber.v("Ignoring synced of local echo for reaction")
                         sum.sourceLocalEcho.remove(txId)
                         sum.sourceEvents.add(reactionEventId)
                     } else {
                         sum.count += 1
                         if (isLocalEcho) {
-                            Timber.v("Adding local echo reaction $reaction")
+                            Timber.v("Adding local echo reaction")
                             sum.sourceLocalEcho.add(txId)
                         } else {
-                            Timber.v("Adding synced reaction $reaction")
+                            Timber.v("Adding synced reaction")
                             sum.sourceEvents.add(reactionEventId)
                         }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt
new file mode 100644
index 00000000000..95e196c7621
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/DefaultLiveLocationAggregationProcessor.kt
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.room.aggregation.livelocation
+
+import io.realm.Realm
+import org.matrix.android.sdk.api.extensions.orFalse
+import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent
+import org.matrix.android.sdk.internal.database.mapper.ContentMapper
+import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
+import org.matrix.android.sdk.internal.database.query.getOrNull
+import timber.log.Timber
+import javax.inject.Inject
+
+internal class DefaultLiveLocationAggregationProcessor @Inject constructor() : LiveLocationAggregationProcessor {
+
+    override fun handleLiveLocation(realm: Realm, event: Event, content: MessageLiveLocationContent, roomId: String, isLocalEcho: Boolean) {
+        val locationSenderId = event.senderId ?: return
+
+        // We shouldn't process local echos
+        if (isLocalEcho) {
+            return
+        }
+
+        // A beacon info state event has to be sent before sending location
+        // TODO handle missing check of m_relatesTo field
+        var beaconInfoEntity: CurrentStateEventEntity? = null
+        val eventTypesIterator = EventType.STATE_ROOM_BEACON_INFO.iterator()
+        while (beaconInfoEntity == null && eventTypesIterator.hasNext()) {
+            beaconInfoEntity = CurrentStateEventEntity.getOrNull(realm, roomId, locationSenderId, eventTypesIterator.next())
+        }
+
+        if (beaconInfoEntity == null) {
+            Timber.v("## LIVE LOCATION. There is not any beacon info which should be emitted before sending location updates")
+            return
+        }
+        val beaconInfoContent = ContentMapper.map(beaconInfoEntity.root?.content)?.toModel(catchError = true)
+        if (beaconInfoContent == null) {
+            Timber.v("## LIVE LOCATION. Beacon info content is invalid")
+            return
+        }
+
+        // Check if live location is ended
+        if (!beaconInfoContent.getBestBeaconInfo()?.isLive.orFalse()) {
+            Timber.v("## LIVE LOCATION. Beacon info is not live anymore")
+            return
+        }
+
+        // Check if beacon info is outdated
+        if (isBeaconInfoOutdated(beaconInfoContent, content)) {
+            Timber.v("## LIVE LOCATION. Beacon info has timeout")
+            beaconInfoContent.hasTimedOut = true
+        } else {
+            beaconInfoContent.lastLocationContent = content
+        }
+
+        beaconInfoEntity.root?.content = ContentMapper.map(beaconInfoContent.toContent())
+    }
+
+    private fun isBeaconInfoOutdated(beaconInfoContent: LiveLocationBeaconContent,
+                                     liveLocationContent: MessageLiveLocationContent): Boolean {
+        val beaconInfoStartTime = beaconInfoContent.getBestTimestampAsMilliseconds() ?: 0
+        val liveLocationEventTime = liveLocationContent.getBestTimestampAsMilliseconds() ?: 0
+        val timeout = beaconInfoContent.getBestBeaconInfo()?.timeout ?: 0
+        return liveLocationEventTime - beaconInfoStartTime > timeout
+    }
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt
new file mode 100644
index 00000000000..7b5f23e2433
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/aggregation/livelocation/LiveLocationAggregationProcessor.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.android.sdk.internal.session.room.aggregation.livelocation
+
+import io.realm.Realm
+import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent
+
+internal interface LiveLocationAggregationProcessor {
+    fun handleLiveLocation(realm: Realm,
+                           event: Event,
+                           content: MessageLiveLocationContent,
+                           roomId: String,
+                           isLocalEcho: Boolean)
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt
index 71c8c9cd38c..dc3ea55a019 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/alias/GetRoomIdByAliasTask.kt
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room.alias
 import com.zhuinden.monarchy.Monarchy
 import io.realm.Realm
 import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.api.session.room.alias.RoomAliasDescription
 import org.matrix.android.sdk.api.util.Optional
 import org.matrix.android.sdk.internal.database.model.RoomSummaryEntity
 import org.matrix.android.sdk.internal.database.query.findByAlias
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
index c9914449c3c..3b2e9d3d228 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/create/CreateRoomBodyBuilder.kt
@@ -16,6 +16,7 @@
 
 package org.matrix.android.sdk.internal.session.room.create
 
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
@@ -24,7 +25,6 @@ import org.matrix.android.sdk.api.session.identity.toMedium
 import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
 import org.matrix.android.sdk.api.util.MimeTypes
 import org.matrix.android.sdk.internal.crypto.DeviceListManager
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.internal.di.AuthenticatedIdentity
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.network.token.AccessTokenProvider
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
index 3d0f51b831c..70ba9287a2a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/LoadRoomMembersTask.kt
@@ -123,7 +123,7 @@ internal class DefaultLoadRoomMembersTask @Inject constructor(
                     eventId = roomMemberEvent.eventId
                     root = eventEntity
                 }
-                roomMemberEventHandler.handle(realm, roomId, roomMemberEvent)
+                roomMemberEventHandler.handle(realm, roomId, roomMemberEvent, false)
             }
             roomEntity.membersLoadStatus = RoomMembersLoadStatusType.LOADED
             roomSummaryUpdater.update(realm, roomId, updateMembers = true)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt
index 25c124bd6be..85300fa3518 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/RoomMemberEventHandler.kt
@@ -17,6 +17,7 @@
 package org.matrix.android.sdk.internal.session.room.membership
 
 import io.realm.Realm
+import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
@@ -33,23 +34,49 @@ internal class RoomMemberEventHandler @Inject constructor(
         @UserId private val myUserId: String
 ) {
 
-    fun handle(realm: Realm, roomId: String, event: Event, aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean {
+    fun handle(realm: Realm,
+               roomId: String,
+               event: Event,
+               isInitialSync: Boolean,
+               aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean {
         if (event.type != EventType.STATE_ROOM_MEMBER) {
             return false
         }
-        val userId = event.stateKey ?: return false
-        val roomMember = event.getFixedRoomMemberContent()
-        return handle(realm, roomId, userId, roomMember, aggregator)
+        val eventUserId = event.stateKey ?: return false
+        val roomMember = event.getFixedRoomMemberContent() ?: return false
+
+        return if (isInitialSync) {
+            handleInitialSync(realm, roomId, myUserId, eventUserId, roomMember, aggregator)
+        } else {
+            handleIncrementalSync(
+                    realm,
+                    roomId,
+                    eventUserId,
+                    roomMember,
+                    event.resolvedPrevContent(),
+                    aggregator
+            )
+        }
     }
 
-    fun handle(realm: Realm,
-               roomId: String,
-               userId: String,
-               roomMember: RoomMemberContent?,
-               aggregator: SyncResponsePostTreatmentAggregator? = null): Boolean {
-        if (roomMember == null) {
-            return false
+    private fun handleInitialSync(realm: Realm,
+                                  roomId: String,
+                                  currentUserId: String,
+                                  eventUserId: String,
+                                  roomMember: RoomMemberContent,
+                                  aggregator: SyncResponsePostTreatmentAggregator?): Boolean {
+        if (currentUserId != eventUserId) {
+            saveUserEntityLocallyIfNecessary(realm, eventUserId, roomMember)
         }
+        saveRoomMemberEntityLocally(realm, roomId, eventUserId, roomMember)
+        updateDirectChatsIfNecessary(roomId, roomMember, aggregator)
+        return true
+    }
+
+    private fun saveRoomMemberEntityLocally(realm: Realm,
+                                            roomId: String,
+                                            userId: String,
+                                            roomMember: RoomMemberContent) {
         val roomMemberEntity = RoomMemberEntityFactory.create(
                 roomId,
                 userId,
@@ -58,26 +85,58 @@ internal class RoomMemberEventHandler @Inject constructor(
                 // but we want to preserve presence record value and not replace it with null
                 getExistingPresenceState(realm, roomId, userId))
         realm.insertOrUpdate(roomMemberEntity)
+    }
+
+    /**
+     * Get the already existing presence state for a specific user & room in order NOT to be replaced in RoomMemberSummaryEntity
+     * by NULL value.
+     */
+    private fun getExistingPresenceState(realm: Realm, roomId: String, userId: String): UserPresenceEntity? {
+        return RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()?.userPresenceEntity
+    }
+
+    private fun saveUserEntityLocallyIfNecessary(realm: Realm,
+                                                 userId: String,
+                                                 roomMember: RoomMemberContent) {
         if (roomMember.membership.isActive()) {
-            val userEntity = UserEntityFactory.create(userId, roomMember)
-            realm.insertOrUpdate(userEntity)
+            saveUserLocally(realm, userId, roomMember)
         }
+    }
 
+    private fun saveUserLocally(realm: Realm, userId: String, roomMember: RoomMemberContent) {
+        val userEntity = UserEntityFactory.create(userId, roomMember)
+        realm.insertOrUpdate(userEntity)
+    }
+
+    private fun updateDirectChatsIfNecessary(roomId: String,
+                                             roomMember: RoomMemberContent,
+                                             aggregator: SyncResponsePostTreatmentAggregator?) {
         // check whether this new room member event may be used to update the directs dictionary in account data
         // this is required to handle correctly invite by email in DM
         val mxId = roomMember.thirdPartyInvite?.signed?.mxid
         if (mxId != null && mxId != myUserId) {
             aggregator?.directChatsToCheck?.put(roomId, mxId)
         }
-        return true
     }
 
-    /**
-     * Get the already existing presence state for a specific user & room in order NOT to be replaced in RoomMemberSummaryEntity
-     * by NULL value.
-     */
+    private fun handleIncrementalSync(realm: Realm,
+                                      roomId: String,
+                                      eventUserId: String,
+                                      roomMember: RoomMemberContent,
+                                      prevContent: Content?,
+                                      aggregator: SyncResponsePostTreatmentAggregator?): Boolean {
+        if (aggregator != null) {
+            val previousDisplayName = prevContent?.get("displayname") as? String
+            val previousAvatar = prevContent?.get("avatar_url") as? String
 
-    private fun getExistingPresenceState(realm: Realm, roomId: String, userId: String): UserPresenceEntity? {
-        return RoomMemberSummaryEntity.where(realm, roomId, userId).findFirst()?.userPresenceEntity
+            if (previousDisplayName != roomMember.displayName || previousAvatar != roomMember.avatarUrl) {
+                aggregator.userIdsToFetch.add(eventUserId)
+            }
+        }
+
+        saveRoomMemberEntityLocally(realm, roomId, eventUserId, roomMember)
+        // At the end of the sync, fetch all the profiles from the aggregator
+        updateDirectChatsIfNecessary(roomId, roomMember, aggregator)
+        return true
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteBody.kt
index 06b75709a2e..300cc210bca 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/InviteBody.kt
@@ -20,7 +20,7 @@ import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
-data class InviteBody(
+internal data class InviteBody(
         @Json(name = "user_id") val userId: String,
         @Json(name = "reason") val reason: String?
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt
index 22a46b6cfc9..f883cc33ec6 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/membership/joining/JoinRoomTask.kt
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.room.membership.joining
 import io.realm.RealmConfiguration
 import kotlinx.coroutines.TimeoutCancellationException
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.api.session.room.failure.JoinRoomFailure
 import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
 import org.matrix.android.sdk.api.session.room.model.Membership
@@ -30,7 +31,6 @@ import org.matrix.android.sdk.internal.database.query.where
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
 import org.matrix.android.sdk.internal.network.executeRequest
-import org.matrix.android.sdk.internal.session.identity.model.SignInvitationResult
 import org.matrix.android.sdk.internal.session.room.RoomAPI
 import org.matrix.android.sdk.internal.session.room.membership.RoomChangeMembershipStateDataSource
 import org.matrix.android.sdk.internal.session.room.read.SetReadMarkersTask
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt
index b19b8d4a6b6..fe7dc28228e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/prune/RedactionEventProcessor.kt
@@ -86,9 +86,9 @@ internal class RedactionEventProcessor @Inject constructor() : EventInsertLivePr
 //                    }
 
                     val modified = unsignedData.copy(redactedEvent = redactionEvent)
-                    // I Commented the line below, it should not be empty while we lose all the previous info about
-                    // the redacted event
-//                    eventToPrune.content = ContentMapper.map(emptyMap())
+                    // Deleting the content of a thread message will result to delete the thread relation, however threads are now dynamic
+                    // so there is not much of a problem
+                    eventToPrune.content = ContentMapper.map(emptyMap())
                     eventToPrune.unsignedData = MoshiProvider.providesMoshi().adapter(UnsignedData::class.java).toJson(modified)
                     eventToPrune.decryptionResultJson = null
                     eventToPrune.decryptionErrorCode = null
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/FullyReadContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/FullyReadContent.kt
index 9b4db795ec4..00dfe6d29cc 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/FullyReadContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/read/FullyReadContent.kt
@@ -20,6 +20,6 @@ import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
-data class FullyReadContent(
+internal data class FullyReadContent(
         @Json(name = "event_id") val eventId: String
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt
index a46bbe8d9f8..116d4aa0a1a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/relation/threads/FetchThreadTimelineTask.kt
@@ -18,13 +18,13 @@ package org.matrix.android.sdk.internal.session.room.relation.threads
 import com.zhuinden.monarchy.Monarchy
 import io.realm.Realm
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.internal.crypto.CryptoSessionInfoProvider
 import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.mapper.toEntity
@@ -251,7 +251,7 @@ internal class DefaultFetchThreadTimelineTask @Inject constructor(
                     sum = realm.createObject(ReactionAggregatedSummaryEntity::class.java)
                     sum.key = reaction
                     sum.firstTimestamp = event.originServerTs ?: 0
-                    Timber.v("Adding synced reaction $reaction")
+                    Timber.v("Adding synced reaction")
                     sum.count = 1
                     // reactionEventId not included in the /relations API
 //                    sum.sourceEvents.add(reactionEventId)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
index 31c7254ed5e..34e38581d1f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/DefaultSendService.kt
@@ -46,6 +46,7 @@ import org.matrix.android.sdk.api.util.Cancelable
 import org.matrix.android.sdk.api.util.CancelableBag
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.api.util.NoOpCancellable
+import org.matrix.android.sdk.api.util.TextContent
 import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
 import org.matrix.android.sdk.internal.di.SessionId
 import org.matrix.android.sdk.internal.di.WorkManagerProvider
@@ -134,6 +135,12 @@ internal class DefaultSendService @AssistedInject constructor(
                 .let { sendEvent(it) }
     }
 
+    override fun sendLiveLocation(beaconInfoEventId: String, latitude: Double, longitude: Double, uncertainty: Double?): Cancelable {
+        return localEchoEventFactory.createLiveLocationEvent(beaconInfoEventId, roomId, latitude, longitude, uncertainty)
+                .also { createLocalEcho(it) }
+                .let { sendEvent(it) }
+    }
+
     override fun redactEvent(event: Event, reason: String?): Cancelable {
         // TODO manage media/attachements?
         val redactionEcho = localEchoEventFactory.createRedactEvent(roomId, event.eventId!!, reason)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
index 0ba95cc1fb8..bb16563f96a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt
@@ -43,6 +43,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollConte
 import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageFormat
 import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent
+import org.matrix.android.sdk.api.session.room.model.message.MessageLiveLocationContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
 import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
 import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
@@ -64,6 +65,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
 import org.matrix.android.sdk.api.session.room.timeline.isReply
+import org.matrix.android.sdk.api.util.TextContent
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor
 import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
@@ -242,6 +244,32 @@ internal class LocalEchoEventFactory @Inject constructor(
         return createMessageEvent(roomId, content)
     }
 
+    fun createLiveLocationEvent(beaconInfoEventId: String,
+                                roomId: String,
+                                latitude: Double,
+                                longitude: Double,
+                                uncertainty: Double?): Event {
+        val geoUri = buildGeoUri(latitude, longitude, uncertainty)
+        val content = MessageLiveLocationContent(
+                body = geoUri,
+                relatesTo = RelationDefaultContent(
+                        type = RelationType.REFERENCE,
+                        eventId = beaconInfoEventId
+                ),
+                unstableLocationInfo = LocationInfo(geoUri = geoUri, description = geoUri),
+                unstableTimestampAsMilliseconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()),
+        )
+        val localId = LocalEcho.createLocalEchoId()
+        return Event(
+                roomId = roomId,
+                originServerTs = dummyOriginServerTs(),
+                senderId = userId,
+                eventId = localId,
+                type = EventType.BEACON_LOCATION_DATA.first(),
+                content = content.toContent(),
+                unsignedData = UnsignedData(age = null, transactionId = localId))
+    }
+
     fun createReplaceTextOfReply(roomId: String,
                                  eventReplaced: TimelineEvent,
                                  originalEvent: TimelineEvent,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
index ef7945cf8cc..05585a4cb5c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MarkdownParser.kt
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.internal.session.room.send
 
 import org.commonmark.parser.Parser
 import org.commonmark.renderer.html.HtmlRenderer
+import org.matrix.android.sdk.api.util.TextContent
 import org.matrix.android.sdk.internal.session.room.AdvancedCommonmarkParser
 import org.matrix.android.sdk.internal.session.room.SimpleCommonmarkParser
 import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
index f44c255f1e0..b59f1b174f2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/MultipleEventSendingDispatcherWorker.kt
@@ -29,7 +29,6 @@ import org.matrix.android.sdk.internal.session.room.timeline.TimelineSendEventWo
 import org.matrix.android.sdk.internal.worker.SessionSafeCoroutineWorker
 import org.matrix.android.sdk.internal.worker.SessionWorkerParams
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
-import org.matrix.android.sdk.internal.worker.startChain
 import timber.log.Timber
 import javax.inject.Inject
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt
similarity index 86%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContent.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt
index 93c0167abe8..8caa99d90a2 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/TextContentExtension.kt
@@ -24,18 +24,9 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon
 import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
 import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromHtmlReply
 import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply
+import org.matrix.android.sdk.api.util.TextContent
 
-/**
- * Contains a text and eventually a formatted text
- */
-data class TextContent(
-        val text: String,
-        val formattedText: String? = null
-) {
-    fun takeFormatted() = formattedText ?: text
-}
-
-fun TextContent.toMessageTextContent(msgType: String = MessageType.MSGTYPE_TEXT): MessageTextContent {
+internal fun TextContent.toMessageTextContent(msgType: String = MessageType.MSGTYPE_TEXT): MessageTextContent {
     return MessageTextContent(
             msgType = msgType,
             format = MessageFormat.FORMAT_MATRIX_HTML.takeIf { formattedText != null },
@@ -49,7 +40,7 @@ fun TextContent.toMessageTextContent(msgType: String = MessageType.MSGTYPE_TEXT)
  * latestThreadEventId in order for the clients without threads enabled to render it appropriately
  * If latest event not found, we pass rootThreadEventId
  */
-fun TextContent.toThreadTextContent(
+internal fun TextContent.toThreadTextContent(
         rootThreadEventId: String,
         latestThreadEventId: String,
         msgType: String = MessageType.MSGTYPE_TEXT): MessageTextContent {
@@ -68,7 +59,7 @@ fun TextContent.toThreadTextContent(
     )
 }
 
-fun TextContent.removeInReplyFallbacks(): TextContent {
+internal fun TextContent.removeInReplyFallbacks(): TextContent {
     return copy(
             text = extractUsefulTextFromReply(this.text),
             formattedText = this.formattedText?.let { extractUsefulTextFromHtmlReply(it) }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
index 417417f4394..89d33f98d21 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/DefaultStateService.kt
@@ -21,16 +21,20 @@ import androidx.lifecycle.LiveData
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.query.QueryStringValue
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.GuestAccess
 import org.matrix.android.sdk.api.session.room.model.RoomCanonicalAliasContent
 import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
 import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
 import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesAllowEntry
 import org.matrix.android.sdk.api.session.room.model.RoomJoinRulesContent
+import org.matrix.android.sdk.api.session.room.model.livelocation.BeaconInfo
+import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent
 import org.matrix.android.sdk.api.session.room.state.StateService
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.api.util.MimeTypes
@@ -186,4 +190,42 @@ internal class DefaultStateService @AssistedInject constructor(@Assisted private
         }
         updateJoinRule(RoomJoinRules.RESTRICTED, null, allowEntries)
     }
+
+    override suspend fun stopLiveLocation(userId: String) {
+        getLiveLocationBeaconInfo(userId, true)?.let { beaconInfoStateEvent ->
+            beaconInfoStateEvent.getClearContent()?.toModel()?.let { content ->
+                val beaconContent = LiveLocationBeaconContent(
+                        unstableBeaconInfo = BeaconInfo(
+                                description = content.getBestBeaconInfo()?.description,
+                                timeout = content.getBestBeaconInfo()?.timeout,
+                                isLive = false,
+                        ),
+                        unstableTimestampAsMilliseconds = System.currentTimeMillis()
+                ).toContent()
+
+                beaconInfoStateEvent.stateKey?.let {
+                    sendStateEvent(
+                            eventType = EventType.STATE_ROOM_BEACON_INFO.first(),
+                            body = beaconContent,
+                            stateKey = it
+                    )
+                }
+            }
+        }
+    }
+
+    override suspend fun getLiveLocationBeaconInfo(userId: String, filterOnlyLive: Boolean): Event? {
+        return EventType.STATE_ROOM_BEACON_INFO
+                .mapNotNull {
+                    stateEventDataSource.getStateEvent(
+                            roomId = roomId,
+                            eventType = it,
+                            stateKey = QueryStringValue.Equals(userId)
+                    )
+                }
+                .firstOrNull { beaconInfoEvent ->
+                    !filterOnlyLive ||
+                            beaconInfoEvent.getClearContent()?.toModel()?.getBestBeaconInfo()?.isLive.orFalse()
+                }
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt
index 2114b9c5901..42d66774094 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/state/StateEventDataSource.kt
@@ -32,7 +32,6 @@ import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
 import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntityFields
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.query.QueryStringValueProcessor
-import org.matrix.android.sdk.internal.query.process
 import javax.inject.Inject
 
 internal class StateEventDataSource @Inject constructor(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt
index b7e6548b54f..e3a215445db 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/GraphUtils.kt
@@ -18,16 +18,16 @@ package org.matrix.android.sdk.internal.session.room.summary
 
 import java.util.LinkedList
 
-data class GraphNode(
+internal data class GraphNode(
         val name: String
 )
 
-data class GraphEdge(
+internal data class GraphEdge(
         val source: GraphNode,
         val destination: GraphNode
 )
 
-class Graph {
+internal class Graph {
 
     private val adjacencyList: HashMap> = HashMap()
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt
index c9d84b1b935..3af579d0507 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/summary/RoomSummaryUpdater.kt
@@ -22,6 +22,7 @@ import kotlinx.coroutines.runBlocking
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataTypes
 import org.matrix.android.sdk.api.session.room.model.Membership
@@ -40,7 +41,6 @@ import org.matrix.android.sdk.api.session.sync.model.RoomSyncSummary
 import org.matrix.android.sdk.api.session.sync.model.RoomSyncUnreadNotifications
 import org.matrix.android.sdk.internal.crypto.EventDecryptor
 import org.matrix.android.sdk.internal.crypto.crosssigning.DefaultCrossSigningService
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
 import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.model.CurrentStateEventEntity
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
index 8c2b4d2bbe2..5064ebf49b3 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt
@@ -35,7 +35,7 @@ import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.room.timeline.Timeline
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
 import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
 import org.matrix.android.sdk.internal.session.room.relation.threads.FetchThreadTimelineTask
@@ -223,7 +223,15 @@ internal class DefaultTimeline(private val roomId: String,
         updateState(direction) {
             it.copy(loading = true)
         }
-        val loadMoreResult = strategy.loadMore(count, direction, fetchOnServerIfNeeded)
+        val loadMoreResult = try {
+            strategy.loadMore(count, direction, fetchOnServerIfNeeded)
+        } catch (throwable: Throwable) {
+            // Timeline could not be loaded with a (likely) permanent issue, such as the
+            // server now knowing the initialEventId, so we want to show an error message
+            // and possibly restart without initialEventId.
+            onTimelineFailure(throwable)
+            return false
+        }
         Timber.v("$baseLogMessage: result $loadMoreResult")
         val hasMoreToLoad = loadMoreResult != LoadMoreResult.REACHED_END
         updateState(direction) {
@@ -342,6 +350,14 @@ internal class DefaultTimeline(private val roomId: String,
         }
     }
 
+    private fun onTimelineFailure(throwable: Throwable) {
+        timelineScope.launch(coroutineDispatchers.main) {
+            listeners.forEach {
+                tryOrNull { it.onTimelineFailure(throwable) }
+            }
+        }
+    }
+
     private fun buildStrategy(mode: LoadTimelineStrategy.Mode): LoadTimelineStrategy {
         return LoadTimelineStrategy(
                 roomId = roomId,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt
index 1ba2aff191e..826c9d7c48e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimelineService.kt
@@ -26,8 +26,8 @@ import org.matrix.android.sdk.api.session.room.timeline.Timeline
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.TimelineService
 import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.api.util.Optional
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.session.room.membership.LoadRoomMembersTask
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt
index 9ede2f6562f..5bca5118b82 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/GetEventTask.kt
@@ -17,9 +17,9 @@
 package org.matrix.android.sdk.internal.session.room.timeline
 
 import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.internal.crypto.EventDecryptor
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 import org.matrix.android.sdk.internal.network.GlobalErrorReceiver
 import org.matrix.android.sdk.internal.network.executeRequest
 import org.matrix.android.sdk.internal.session.room.RoomAPI
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt
index a9e7b3bcdc4..ff986d04af1 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt
@@ -24,12 +24,14 @@ import io.realm.RealmResults
 import io.realm.kotlin.createObject
 import kotlinx.coroutines.CompletableDeferred
 import org.matrix.android.sdk.api.extensions.orFalse
+import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.failure.MatrixError
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.session.room.timeline.Timeline
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.helper.addIfNecessary
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
 import org.matrix.android.sdk.internal.database.model.ChunkEntity
 import org.matrix.android.sdk.internal.database.model.ChunkEntityFields
@@ -194,6 +196,10 @@ internal class LoadTimelineStrategy(
                 getContextLatch?.await()
                 getContextLatch = null
             } catch (failure: Throwable) {
+                if (failure is Failure.ServerError && failure.error.code in listOf(MatrixError.M_NOT_FOUND, MatrixError.M_FORBIDDEN)) {
+                    // This failure is likely permanent, so handle in DefaultTimeline to restart without eventId
+                    throw failure
+                }
                 return LoadMoreResult.FAILURE
             }
         }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt
index c8f2132ae66..4ead1d4ecba 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineChunk.kt
@@ -30,7 +30,7 @@ import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.room.timeline.Timeline
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.EventMapper
 import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
 import org.matrix.android.sdk.internal.database.model.ChunkEntity
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
index 3ddd877b789..5c30dc20d9d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TimelineEventDecryptor.kt
@@ -20,11 +20,10 @@ import io.realm.RealmConfiguration
 import kotlinx.coroutines.runBlocking
 import org.matrix.android.sdk.api.session.crypto.CryptoService
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
+import org.matrix.android.sdk.api.session.crypto.NewSessionListener
 import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.internal.crypto.NewSessionListener
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.model.EventEntity
 import org.matrix.android.sdk.internal.database.query.where
@@ -40,7 +39,6 @@ internal class TimelineEventDecryptor @Inject constructor(
         private val realmConfiguration: RealmConfiguration,
         private val cryptoService: CryptoService,
         private val threadsAwarenessHandler: ThreadsAwarenessHandler,
-        private val lightweightSettingsStorage: LightweightSettingsStorage
 ) {
 
     private val newSessionListener = object : NewSessionListener {
@@ -113,15 +111,16 @@ internal class TimelineEventDecryptor @Inject constructor(
 
     private fun threadAwareNonEncryptedEvents(request: DecryptionRequest, realm: Realm) {
         val event = request.event
-            realm.executeTransaction {
-                val eventId = event.eventId ?: return@executeTransaction
-                val eventEntity = EventEntity
-                        .where(it, eventId = eventId)
-                        .findFirst()
-                val decryptedEvent = eventEntity?.asDomain()
-                threadsAwarenessHandler.makeEventThreadAware(realm, event.roomId, decryptedEvent, eventEntity)
+        realm.executeTransaction {
+            val eventId = event.eventId ?: return@executeTransaction
+            val eventEntity = EventEntity
+                    .where(it, eventId = eventId)
+                    .findFirst()
+            val decryptedEvent = eventEntity?.asDomain()
+            threadsAwarenessHandler.makeEventThreadAware(realm, event.roomId, decryptedEvent, eventEntity)
         }
     }
+
     private suspend fun processDecryptRequest(request: DecryptionRequest, realm: Realm) {
         val event = request.event
         val timelineId = request.timelineId
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
index 63383a99b3c..d3f24a8568a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/TokenChunkEventPersistor.kt
@@ -23,11 +23,11 @@ import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
 import org.matrix.android.sdk.api.session.room.send.SendState
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.helper.addIfNecessary
 import org.matrix.android.sdk.internal.database.helper.addStateEvent
 import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
 import org.matrix.android.sdk.internal.database.helper.updateThreadSummaryIfNeeded
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.toEntity
 import org.matrix.android.sdk.internal.database.model.ChunkEntity
 import org.matrix.android.sdk.internal.database.model.EventEntity
@@ -38,6 +38,7 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntityFields
 import org.matrix.android.sdk.internal.database.query.copyToRealmOrIgnore
 import org.matrix.android.sdk.internal.database.query.create
 import org.matrix.android.sdk.internal.database.query.find
+import org.matrix.android.sdk.internal.database.query.findAll
 import org.matrix.android.sdk.internal.database.query.where
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.di.UserId
@@ -80,7 +81,8 @@ internal class TokenChunkEventPersistor @Inject constructor(
 
                     val existingChunk = ChunkEntity.find(realm, roomId, prevToken = prevToken, nextToken = nextToken)
                     if (existingChunk != null) {
-                        Timber.v("This chunk is already in the db, returns")
+                        Timber.v("This chunk is already in the db, checking if this might be caused by broken links")
+                        existingChunk.fixChunkLinks(realm, roomId, direction, prevToken, nextToken)
                         return@awaitTransaction
                     }
                     val prevChunk = ChunkEntity.find(realm, roomId, nextToken = prevToken)
@@ -89,8 +91,14 @@ internal class TokenChunkEventPersistor @Inject constructor(
                         this.nextChunk = nextChunk
                         this.prevChunk = prevChunk
                     }
-                    nextChunk?.prevChunk = currentChunk
-                    prevChunk?.nextChunk = currentChunk
+                    val allNextChunks = ChunkEntity.findAll(realm, roomId, prevToken = nextToken)
+                    val allPrevChunks = ChunkEntity.findAll(realm, roomId, nextToken = prevToken)
+                    allNextChunks?.forEach {
+                        it.prevChunk = currentChunk
+                    }
+                    allPrevChunks?.forEach {
+                        it.nextChunk = currentChunk
+                    }
                     if (receivedChunk.events.isEmpty() && !receivedChunk.hasMore()) {
                         handleReachEnd(roomId, direction, currentChunk)
                     } else {
@@ -109,6 +117,34 @@ internal class TokenChunkEventPersistor @Inject constructor(
         }
     }
 
+    private fun ChunkEntity.fixChunkLinks(
+            realm: Realm,
+            roomId: String,
+            direction: PaginationDirection,
+            prevToken: String?,
+            nextToken: String?,
+    ) {
+        if (direction == PaginationDirection.FORWARDS) {
+            val prevChunks = ChunkEntity.findAll(realm, roomId, nextToken = prevToken)
+            Timber.v("Found ${prevChunks?.size} prevChunks")
+            prevChunks?.forEach {
+                if (it.nextChunk != this) {
+                    Timber.i("Set nextChunk for ${it.identifier()} from ${it.nextChunk?.identifier()} to ${identifier()}")
+                    it.nextChunk = this
+                }
+            }
+        } else {
+            val nextChunks = ChunkEntity.findAll(realm, roomId, prevToken = nextToken)
+            Timber.v("Found ${nextChunks?.size} nextChunks")
+            nextChunks?.forEach {
+                if (it.prevChunk != this) {
+                    Timber.i("Set prevChunk for ${it.identifier()} from ${it.prevChunk?.identifier()} to ${identifier()}")
+                    it.prevChunk = this
+                }
+            }
+        }
+    }
+
     private fun handleReachEnd(roomId: String, direction: PaginationDirection, currentChunk: ChunkEntity) {
         Timber.v("Reach end of $roomId")
         if (direction == PaginationDirection.FORWARDS) {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingBody.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingBody.kt
index 973870bb47f..66913e0cbfb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingBody.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingBody.kt
@@ -20,7 +20,7 @@ import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
-data class TypingBody(
+internal data class TypingBody(
         // Required. Whether the user is typing or not. If false, the timeout key can be omitted.
         @Json(name = "typing")
         val typing: Boolean,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingEventContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingEventContent.kt
index 488d38d762d..5b010856485 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingEventContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/typing/TypingEventContent.kt
@@ -20,7 +20,7 @@ import com.squareup.moshi.Json
 import com.squareup.moshi.JsonClass
 
 @JsonClass(generateAdapter = true)
-data class TypingEventContent(
+internal data class TypingEventContent(
         @Json(name = "user_ids")
         val typingUserIds: List = emptyList()
 )
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
index 028c3e91933..7daf506c14d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/uploads/GetUploadsTask.kt
@@ -17,6 +17,7 @@
 package org.matrix.android.sdk.internal.session.room.uploads
 
 import com.zhuinden.monarchy.Monarchy
+import io.realm.Sort
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -75,6 +76,7 @@ internal class DefaultGetUploadsTask @Inject constructor(
             monarchy.doWithRealm { realm ->
                 eventsFromRealm = EventEntity.whereType(realm, EventType.ENCRYPTED, params.roomId)
                         .like(EventEntityFields.DECRYPTION_RESULT_JSON, TimelineEventFilter.DecryptedContent.URL)
+                        .sort(EventEntityFields.ORIGIN_SERVER_TS, Sort.DESCENDING)
                         .findAll()
                         .map { it.asDomain() }
                         // Exclude stickers
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
index fad1840e51b..17dc90fdb0e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/securestorage/SecretStoringUtils.kt
@@ -34,7 +34,6 @@ import java.io.InputStream
 import java.io.ObjectInputStream
 import java.io.ObjectOutputStream
 import java.io.OutputStream
-import java.lang.IllegalArgumentException
 import java.math.BigInteger
 import java.security.KeyPairGenerator
 import java.security.KeyStore
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt
index e764ab551ae..05cff7dd89f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/DefaultSpaceService.kt
@@ -43,6 +43,7 @@ import org.matrix.android.sdk.api.session.space.SpaceService
 import org.matrix.android.sdk.api.session.space.SpaceSummaryQueryParams
 import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
 import org.matrix.android.sdk.api.session.space.model.SpaceParentContent
+import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult
 import org.matrix.android.sdk.internal.di.UserId
 import org.matrix.android.sdk.internal.session.room.RoomGetter
 import org.matrix.android.sdk.internal.session.room.SpaceGetter
@@ -51,7 +52,6 @@ import org.matrix.android.sdk.internal.session.room.membership.leaving.LeaveRoom
 import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
 import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryDataSource
 import org.matrix.android.sdk.internal.session.space.peeking.PeekSpaceTask
-import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult
 import javax.inject.Inject
 
 internal class DefaultSpaceService @Inject constructor(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/PeekSpaceTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/PeekSpaceTask.kt
index c45d4420ae4..3647941998a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/PeekSpaceTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/space/peeking/PeekSpaceTask.kt
@@ -23,6 +23,11 @@ import org.matrix.android.sdk.api.session.room.model.RoomType
 import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
 import org.matrix.android.sdk.api.session.room.peeking.PeekResult
 import org.matrix.android.sdk.api.session.space.model.SpaceChildContent
+import org.matrix.android.sdk.api.session.space.peeking.ISpaceChild
+import org.matrix.android.sdk.api.session.space.peeking.SpaceChildPeekResult
+import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult
+import org.matrix.android.sdk.api.session.space.peeking.SpacePeekSummary
+import org.matrix.android.sdk.api.session.space.peeking.SpaceSubChildPeekResult
 import org.matrix.android.sdk.internal.session.room.peeking.PeekRoomTask
 import org.matrix.android.sdk.internal.session.room.peeking.ResolveRoomStateTask
 import org.matrix.android.sdk.internal.task.Task
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt
index 8c68e224dcd..ef9f468c864 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/RoomSyncEphemeralTemporaryStore.kt
@@ -21,8 +21,8 @@ import com.squareup.moshi.Moshi
 import okio.buffer
 import okio.source
 import org.matrix.android.sdk.api.session.sync.model.RoomSyncEphemeral
+import org.matrix.android.sdk.api.util.md5
 import org.matrix.android.sdk.internal.di.SessionFilesDirectory
-import org.matrix.android.sdk.internal.util.md5
 import timber.log.Timber
 import java.io.File
 import javax.inject.Inject
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt
index 18e17c7d139..4f1fe43b7dd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncPresence.kt
@@ -16,6 +16,8 @@
 
 package org.matrix.android.sdk.internal.session.sync
 
+import org.matrix.android.sdk.api.session.presence.model.PresenceEnum
+
 /**
  * For `set_presence` parameter in the /sync request
  *
@@ -24,8 +26,19 @@ package org.matrix.android.sdk.internal.session.sync
  * parameter is set to "offline" then the client is not marked as being online when it uses this API.
  * When set to "unavailable", the client is marked as being idle. One of: ["offline", "online", "unavailable"]
  */
-enum class SyncPresence(val value: String) {
+internal enum class SyncPresence(val value: String) {
     Offline("offline"),
     Online("online"),
-    Unavailable("unavailable")
+    Unavailable("unavailable");
+
+    companion object {
+        fun from(presenceEnum: PresenceEnum): SyncPresence {
+            return when (presenceEnum) {
+                PresenceEnum.ONLINE -> Online
+                PresenceEnum.OFFLINE -> Offline
+                PresenceEnum.UNAVAILABLE -> Unavailable
+            }
+        }
+        fun from(s: String?): SyncPresence? = values().find { it.value == s }
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt
index 1bbf54a7888..97850e81d32 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponseHandler.kt
@@ -26,7 +26,6 @@ import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
 import org.matrix.android.sdk.internal.SessionManager
 import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.di.SessionId
 import org.matrix.android.sdk.internal.di.WorkManagerProvider
@@ -42,7 +41,6 @@ import org.matrix.android.sdk.internal.session.sync.handler.PresenceSyncHandler
 import org.matrix.android.sdk.internal.session.sync.handler.SyncResponsePostTreatmentAggregatorHandler
 import org.matrix.android.sdk.internal.session.sync.handler.UserAccountDataSyncHandler
 import org.matrix.android.sdk.internal.session.sync.handler.room.RoomSyncHandler
-import org.matrix.android.sdk.internal.session.sync.handler.room.ThreadsAwarenessHandler
 import org.matrix.android.sdk.internal.util.awaitTransaction
 import org.matrix.android.sdk.internal.worker.WorkerParamsFactory
 import timber.log.Timber
@@ -65,10 +63,8 @@ internal class SyncResponseHandler @Inject constructor(
         private val aggregatorHandler: SyncResponsePostTreatmentAggregatorHandler,
         private val cryptoService: DefaultCryptoService,
         private val tokenStore: SyncTokenStore,
-        private val lightweightSettingsStorage: LightweightSettingsStorage,
         private val processEventForPushTask: ProcessEventForPushTask,
         private val pushRuleService: PushRuleService,
-        private val threadsAwarenessHandler: ThreadsAwarenessHandler,
         private val presenceSyncHandler: PresenceSyncHandler
 ) {
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt
index fe44531390b..e9452c59fcd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncResponsePostTreatmentAggregator.kt
@@ -22,4 +22,7 @@ internal class SyncResponsePostTreatmentAggregator {
 
     // Map of roomId to directUserId
     val directChatsToCheck = mutableMapOf()
+
+    // List of userIds to fetch and update at the end of incremental syncs
+    val userIdsToFetch = mutableListOf()
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt
index 2136259f22a..b56f8977498 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/SyncTask.kt
@@ -24,6 +24,8 @@ import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.initsync.InitSyncStep
 import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import org.matrix.android.sdk.api.session.statistics.StatisticEvent
+import org.matrix.android.sdk.api.session.sync.InitialSyncStrategy
+import org.matrix.android.sdk.api.session.sync.initialSyncStrategy
 import org.matrix.android.sdk.api.session.sync.model.LazyRoomSyncEphemeral
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
 import org.matrix.android.sdk.internal.di.SessionFilesDirectory
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt
index 9ae7b827777..429f4985334 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/CryptoSyncHandler.kt
@@ -18,16 +18,16 @@ package org.matrix.android.sdk.internal.session.sync.handler
 
 import org.matrix.android.sdk.api.logger.LoggerTag
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
+import org.matrix.android.sdk.api.session.crypto.model.MXEventDecryptionResult
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageContent
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
 import org.matrix.android.sdk.api.session.sync.model.ToDeviceSyncResponse
 import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
-import org.matrix.android.sdk.internal.crypto.MXEventDecryptionResult
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
-import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent
 import org.matrix.android.sdk.internal.crypto.verification.DefaultVerificationService
 import org.matrix.android.sdk.internal.session.initsync.ProgressReporter
 import timber.log.Timber
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt
index e5bed121819..6a7af1dda4a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/PresenceSyncHandler.kt
@@ -31,26 +31,24 @@ import javax.inject.Inject
 internal class PresenceSyncHandler @Inject constructor(private val matrixConfiguration: MatrixConfiguration) {
 
     fun handle(realm: Realm, presenceSyncResponse: PresenceSyncResponse?) {
-        if (matrixConfiguration.presenceSyncEnabled) {
-            presenceSyncResponse?.events
-                    ?.filter { event -> event.type == EventType.PRESENCE }
-                    ?.forEach { event ->
-                        val content = event.getPresenceContent() ?: return@forEach
-                        val userId = event.senderId ?: return@forEach
-                        val userPresenceEntity = UserPresenceEntity(
-                                userId = userId,
-                                lastActiveAgo = content.lastActiveAgo,
-                                statusMessage = content.statusMessage,
-                                isCurrentlyActive = content.isCurrentlyActive,
-                                avatarUrl = content.avatarUrl,
-                                displayName = content.displayName
-                        ).also {
-                            it.presence = content.presence
-                        }
-
-                        storePresenceToDB(realm, userPresenceEntity)
+        presenceSyncResponse?.events
+                ?.filter { event -> event.type == EventType.PRESENCE }
+                ?.forEach { event ->
+                    val content = event.getPresenceContent() ?: return@forEach
+                    val userId = event.senderId ?: return@forEach
+                    val userPresenceEntity = UserPresenceEntity(
+                            userId = userId,
+                            lastActiveAgo = content.lastActiveAgo,
+                            statusMessage = content.statusMessage,
+                            isCurrentlyActive = content.isCurrentlyActive,
+                            avatarUrl = content.avatarUrl,
+                            displayName = content.displayName
+                    ).also {
+                        it.presence = content.presence
                     }
-        }
+
+                    storePresenceToDB(realm, userPresenceEntity)
+                }
     }
 
     /**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt
index 1e0e87a450e..c638ed4f808 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/SyncResponsePostTreatmentAggregatorHandler.kt
@@ -16,22 +16,32 @@
 
 package org.matrix.android.sdk.internal.session.sync.handler
 
+import com.zhuinden.monarchy.Monarchy
 import org.matrix.android.sdk.api.MatrixPatterns
+import org.matrix.android.sdk.api.extensions.tryOrNull
+import org.matrix.android.sdk.api.session.user.model.User
+import org.matrix.android.sdk.internal.di.SessionDatabase
+import org.matrix.android.sdk.internal.session.profile.GetProfileInfoTask
 import org.matrix.android.sdk.internal.session.sync.RoomSyncEphemeralTemporaryStore
 import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator
 import org.matrix.android.sdk.internal.session.sync.model.accountdata.toMutable
+import org.matrix.android.sdk.internal.session.user.UserEntityFactory
 import org.matrix.android.sdk.internal.session.user.accountdata.DirectChatsHelper
 import org.matrix.android.sdk.internal.session.user.accountdata.UpdateUserAccountDataTask
+import org.matrix.android.sdk.internal.util.awaitTransaction
 import javax.inject.Inject
 
 internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor(
         private val directChatsHelper: DirectChatsHelper,
         private val ephemeralTemporaryStore: RoomSyncEphemeralTemporaryStore,
-        private val updateUserAccountDataTask: UpdateUserAccountDataTask
+        private val updateUserAccountDataTask: UpdateUserAccountDataTask,
+        private val getProfileInfoTask: GetProfileInfoTask,
+        @SessionDatabase private val monarchy: Monarchy,
 ) {
-    suspend fun handle(synResHaResponsePostTreatmentAggregator: SyncResponsePostTreatmentAggregator) {
-        cleanupEphemeralFiles(synResHaResponsePostTreatmentAggregator.ephemeralFilesToDelete)
-        updateDirectUserIds(synResHaResponsePostTreatmentAggregator.directChatsToCheck)
+    suspend fun handle(aggregator: SyncResponsePostTreatmentAggregator) {
+        cleanupEphemeralFiles(aggregator.ephemeralFilesToDelete)
+        updateDirectUserIds(aggregator.directChatsToCheck)
+        fetchAndUpdateUsers(aggregator.userIdsToFetch)
     }
 
     private fun cleanupEphemeralFiles(ephemeralFilesToDelete: List) {
@@ -59,13 +69,33 @@ internal class SyncResponsePostTreatmentAggregatorHandler @Inject constructor(
                         }
 
                 // remove roomId from currentDirectUserId entry
-                hasUpdate = hasUpdate or(directChats[currentDirectUserId]?.remove(roomId) == true)
+                hasUpdate = hasUpdate or (directChats[currentDirectUserId]?.remove(roomId) == true)
                 // remove currentDirectUserId entry if there is no attached room anymore
-                hasUpdate = hasUpdate or(directChats.takeIf { it[currentDirectUserId].isNullOrEmpty() }?.remove(currentDirectUserId) != null)
+                hasUpdate = hasUpdate or (directChats.takeIf { it[currentDirectUserId].isNullOrEmpty() }?.remove(currentDirectUserId) != null)
             }
         }
         if (hasUpdate) {
             updateUserAccountDataTask.execute(UpdateUserAccountDataTask.DirectChatParams(directMessages = directChats))
         }
     }
+
+    private suspend fun fetchAndUpdateUsers(userIdsToFetch: List) {
+        fetchUsers(userIdsToFetch)
+                .takeIf { it.isNotEmpty() }
+                ?.saveLocally()
+    }
+
+    private suspend fun fetchUsers(userIdsToFetch: List) = userIdsToFetch.mapNotNull {
+        tryOrNull {
+            val profileJson = getProfileInfoTask.execute(GetProfileInfoTask.Params(it))
+            User.fromJson(it, profileJson)
+        }
+    }
+
+    private suspend fun List.saveLocally() {
+        val userEntities = map { user -> UserEntityFactory.create(user) }
+        monarchy.awaitTransaction {
+            it.insertOrUpdate(userEntities)
+        }
+    }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt
index 025ee329f8a..2c84f1e692f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ReadReceiptHandler.kt
@@ -33,7 +33,7 @@ import javax.inject.Inject
 // value : dict key $UserId
 //              value dict key ts
 //                    dict value ts value
-typealias ReadReceiptContent = Map>>>
+internal typealias ReadReceiptContent = Map>>>
 
 private const val READ_KEY = "m.read"
 private const val TIMESTAMP_KEY = "ts"
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt
index 8fe85f0d318..afd8e1bb99a 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/RoomSyncHandler.kt
@@ -20,7 +20,9 @@ import dagger.Lazy
 import io.realm.Realm
 import io.realm.kotlin.createObject
 import kotlinx.coroutines.runBlocking
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -30,18 +32,18 @@ import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.session.room.threads.model.ThreadSummaryUpdateType
+import org.matrix.android.sdk.api.session.sync.InitialSyncStrategy
+import org.matrix.android.sdk.api.session.sync.initialSyncStrategy
 import org.matrix.android.sdk.api.session.sync.model.InvitedRoomSync
 import org.matrix.android.sdk.api.session.sync.model.LazyRoomSyncEphemeral
 import org.matrix.android.sdk.api.session.sync.model.RoomSync
 import org.matrix.android.sdk.api.session.sync.model.RoomsSyncResponse
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.crypto.DefaultCryptoService
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 import org.matrix.android.sdk.internal.database.helper.addIfNecessary
 import org.matrix.android.sdk.internal.database.helper.addTimelineEvent
 import org.matrix.android.sdk.internal.database.helper.createOrUpdate
 import org.matrix.android.sdk.internal.database.helper.updateThreadSummaryIfNeeded
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.asDomain
 import org.matrix.android.sdk.internal.database.mapper.toEntity
 import org.matrix.android.sdk.internal.database.model.ChunkEntity
@@ -74,9 +76,7 @@ import org.matrix.android.sdk.internal.session.room.summary.RoomSummaryUpdater
 import org.matrix.android.sdk.internal.session.room.timeline.PaginationDirection
 import org.matrix.android.sdk.internal.session.room.timeline.TimelineInput
 import org.matrix.android.sdk.internal.session.room.typing.TypingEventContent
-import org.matrix.android.sdk.internal.session.sync.InitialSyncStrategy
 import org.matrix.android.sdk.internal.session.sync.SyncResponsePostTreatmentAggregator
-import org.matrix.android.sdk.internal.session.sync.initialSyncStrategy
 import org.matrix.android.sdk.internal.session.sync.parsing.RoomSyncAccountDataHandler
 import org.matrix.android.sdk.internal.util.computeBestChunkSize
 import timber.log.Timber
@@ -107,7 +107,6 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                        isInitialSync: Boolean,
                        aggregator: SyncResponsePostTreatmentAggregator,
                        reporter: ProgressReporter? = null) {
-        Timber.v("Execute transaction from $this")
         handleRoomSync(realm, HandlingStrategy.JOINED(roomsSyncResponse.join), isInitialSync, aggregator, reporter)
         handleRoomSync(realm, HandlingStrategy.INVITED(roomsSyncResponse.invite), isInitialSync, aggregator, reporter)
         handleRoomSync(realm, HandlingStrategy.LEFT(roomsSyncResponse.leave), isInitialSync, aggregator, reporter)
@@ -207,6 +206,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                                          syncLocalTimestampMillis: Long,
                                          aggregator: SyncResponsePostTreatmentAggregator): RoomEntity {
         Timber.v("Handle join sync for room $roomId")
+        val isInitialSync = insertType == EventInsertType.INITIAL_SYNC
 
         val ephemeralResult = (roomSync.ephemeral as? LazyRoomSyncEphemeral.Parsed)
                 ?._roomSyncEphemeral
@@ -241,7 +241,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                 }
                 // Give info to crypto module
                 cryptoService.onStateEvent(roomId, event)
-                roomMemberEventHandler.handle(realm, roomId, event, aggregator)
+                roomMemberEventHandler.handle(realm, roomId, event, isInitialSync, aggregator)
             }
         }
         if (roomSync.timeline?.events?.isNotEmpty() == true) {
@@ -283,6 +283,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                                   insertType: EventInsertType,
                                   syncLocalTimestampMillis: Long): RoomEntity {
         Timber.v("Handle invited sync for room $roomId")
+        val isInitialSync = insertType == EventInsertType.INITIAL_SYNC
         val roomEntity = RoomEntity.getOrCreate(realm, roomId)
         roomEntity.membership = Membership.INVITE
         if (roomSync.inviteState != null && roomSync.inviteState.events.isNotEmpty()) {
@@ -296,7 +297,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                     eventId = eventEntity.eventId
                     root = eventEntity
                 }
-                roomMemberEventHandler.handle(realm, roomId, event)
+                roomMemberEventHandler.handle(realm, roomId, event, isInitialSync)
             }
         }
         val inviterEvent = roomSync.inviteState?.events?.lastOrNull {
@@ -312,6 +313,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                                roomSync: RoomSync,
                                insertType: EventInsertType,
                                syncLocalTimestampMillis: Long): RoomEntity {
+        val isInitialSync = insertType == EventInsertType.INITIAL_SYNC
         val roomEntity = RoomEntity.getOrCreate(realm, roomId)
         for (event in roomSync.state?.events.orEmpty()) {
             if (event.eventId == null || event.stateKey == null || event.type == null) {
@@ -323,7 +325,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                 eventId = event.eventId
                 root = eventEntity
             }
-            roomMemberEventHandler.handle(realm, roomId, event)
+            roomMemberEventHandler.handle(realm, roomId, event, isInitialSync)
         }
         for (event in roomSync.timeline?.events.orEmpty()) {
             if (event.eventId == null || event.senderId == null || event.type == null) {
@@ -337,7 +339,7 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                     root = eventEntity
                 }
                 if (event.type == EventType.STATE_ROOM_MEMBER) {
-                    roomMemberEventHandler.handle(realm, roomEntity.roomId, event)
+                    roomMemberEventHandler.handle(realm, roomEntity.roomId, event, isInitialSync)
                 }
             }
         }
@@ -381,11 +383,11 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                 continue
             }
 
-            eventIds.add(event.eventId)
-            liveEventService.get().dispatchLiveEventReceived(event, roomId, insertType == EventInsertType.INITIAL_SYNC)
-
             val isInitialSync = insertType == EventInsertType.INITIAL_SYNC
 
+            eventIds.add(event.eventId)
+            liveEventService.get().dispatchLiveEventReceived(event, roomId, isInitialSync)
+
             if (event.isEncrypted() && !isInitialSync) {
                 runBlocking {
                     decryptIfNeeded(event, roomId)
@@ -404,9 +406,8 @@ internal class RoomSyncHandler @Inject constructor(private val readReceiptHandle
                     root = eventEntity
                 }
                 if (event.type == EventType.STATE_ROOM_MEMBER) {
-                    val fixedContent = event.getFixedRoomMemberContent()
-                    roomMemberContentsByUser[event.stateKey] = fixedContent
-                    roomMemberEventHandler.handle(realm, roomEntity.roomId, event.stateKey, fixedContent, aggregator)
+                    roomMemberContentsByUser[event.stateKey] = event.getFixedRoomMemberContent()
+                    roomMemberEventHandler.handle(realm, roomEntity.roomId, event, isInitialSync, aggregator)
                 }
             }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt
index db9799d51eb..efc8e39a18d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/handler/room/ThreadsAwarenessHandler.kt
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.internal.session.sync.handler.room
 import com.zhuinden.monarchy.Monarchy
 import io.realm.Realm
 import io.realm.kotlin.where
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
@@ -35,9 +36,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageType
 import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.api.util.JsonDict
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import org.matrix.android.sdk.internal.database.mapper.ContentMapper
 import org.matrix.android.sdk.internal.database.mapper.EventMapper
 import org.matrix.android.sdk.internal.database.mapper.asDomain
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
index 2460720adc6..fc6a4e03d64 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/job/SyncThread.kt
@@ -39,8 +39,8 @@ import org.matrix.android.sdk.api.session.sync.SyncState
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
 import org.matrix.android.sdk.internal.network.NetworkConnectivityChecker
 import org.matrix.android.sdk.internal.session.call.ActiveCallHandler
-import org.matrix.android.sdk.internal.session.sync.SyncPresence
 import org.matrix.android.sdk.internal.session.sync.SyncTask
+import org.matrix.android.sdk.internal.settings.DefaultLightweightSettingsStorage
 import org.matrix.android.sdk.internal.util.BackgroundDetectionObserver
 import org.matrix.android.sdk.internal.util.Debouncer
 import org.matrix.android.sdk.internal.util.createUIHandler
@@ -59,7 +59,8 @@ private val loggerTag = LoggerTag("SyncThread", LoggerTag.SYNC)
 internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
                                               private val networkConnectivityChecker: NetworkConnectivityChecker,
                                               private val backgroundDetectionObserver: BackgroundDetectionObserver,
-                                              private val activeCallHandler: ActiveCallHandler
+                                              private val activeCallHandler: ActiveCallHandler,
+                                              private val lightweightSettingsStorage: DefaultLightweightSettingsStorage
 ) : Thread("SyncThread"), NetworkConnectivityChecker.Listener, BackgroundDetectionObserver.Listener {
 
     private var state: SyncState = SyncState.Idle
@@ -104,10 +105,12 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
 
     fun pause() = synchronized(lock) {
         if (isStarted) {
-            Timber.tag(loggerTag.value).d("Pause sync...")
+            Timber.tag(loggerTag.value).d("Pause sync... Not cancelling incremental sync")
             isStarted = false
             retryNoNetworkTask?.cancel()
-            syncScope.coroutineContext.cancelChildren()
+            // Do not cancel the current incremental sync.
+            // Incremental sync can be long and it requires the user to wait for the treatment to end,
+            // else all is restarted from the beginning each time the user moves the app to foreground.
         }
     }
 
@@ -180,7 +183,8 @@ internal class SyncThread @Inject constructor(private val syncTask: SyncTask,
                     else                            -> DEFAULT_LONG_POOL_TIMEOUT
                 }
                 Timber.tag(loggerTag.value).d("Execute sync request with timeout $timeout")
-                val params = SyncTask.Params(timeout, SyncPresence.Online, afterPause = afterPause)
+                val presence = lightweightSettingsStorage.getSyncPresenceStatus()
+                val params = SyncTask.Params(timeout, presence, afterPause = afterPause)
                 val sync = syncScope.launch {
                     previousSyncResponseHasToDevice = doSync(params)
                 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/DefaultLazyRoomSyncEphemeralJsonAdapter.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/DefaultLazyRoomSyncEphemeralJsonAdapter.kt
index 012470a0768..c83f658bfeb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/DefaultLazyRoomSyncEphemeralJsonAdapter.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/DefaultLazyRoomSyncEphemeralJsonAdapter.kt
@@ -21,9 +21,9 @@ import com.squareup.moshi.JsonAdapter
 import com.squareup.moshi.JsonReader
 import com.squareup.moshi.JsonWriter
 import com.squareup.moshi.ToJson
+import org.matrix.android.sdk.api.session.sync.InitialSyncStrategy
 import org.matrix.android.sdk.api.session.sync.model.LazyRoomSyncEphemeral
 import org.matrix.android.sdk.api.session.sync.model.RoomSyncEphemeral
-import org.matrix.android.sdk.internal.session.sync.InitialSyncStrategy
 import org.matrix.android.sdk.internal.session.sync.RoomSyncEphemeralTemporaryStore
 import timber.log.Timber
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/InitialSyncResponseParser.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/InitialSyncResponseParser.kt
index f00cce2d5e8..de3269ca1e7 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/InitialSyncResponseParser.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/sync/parsing/InitialSyncResponseParser.kt
@@ -19,8 +19,8 @@ package org.matrix.android.sdk.internal.session.sync.parsing
 import com.squareup.moshi.Moshi
 import okio.buffer
 import okio.source
+import org.matrix.android.sdk.api.session.sync.InitialSyncStrategy
 import org.matrix.android.sdk.api.session.sync.model.SyncResponse
-import org.matrix.android.sdk.internal.session.sync.InitialSyncStrategy
 import org.matrix.android.sdk.internal.session.sync.RoomSyncEphemeralTemporaryStore
 import timber.log.Timber
 import java.io.File
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt
index 6205e3e4b16..5f62f40ab3f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/DefaultTermsService.kt
@@ -23,6 +23,7 @@ import org.matrix.android.sdk.api.failure.toRegistrationFlowResponse
 import org.matrix.android.sdk.api.session.accountdata.UserAccountDataTypes
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.terms.GetTermsResponse
+import org.matrix.android.sdk.api.session.terms.TermsResponse
 import org.matrix.android.sdk.api.session.terms.TermsService
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.internal.di.UnauthenticatedWithCertificate
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt
index fb6aff5a9ed..1f117de67e5 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/terms/TermsAPI.kt
@@ -16,6 +16,7 @@
 
 package org.matrix.android.sdk.internal.session.terms
 
+import org.matrix.android.sdk.api.session.terms.TermsResponse
 import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.api.util.emptyJsonDict
 import org.matrix.android.sdk.internal.network.HttpHeaders
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt
index 52b8cc36892..4ffc42e714e 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/DefaultUserService.kt
@@ -18,7 +18,6 @@ package org.matrix.android.sdk.internal.session.user
 
 import androidx.lifecycle.LiveData
 import androidx.paging.PagedList
-import org.matrix.android.sdk.api.session.profile.ProfileService
 import org.matrix.android.sdk.api.session.user.UserService
 import org.matrix.android.sdk.api.session.user.model.User
 import org.matrix.android.sdk.api.util.Optional
@@ -37,16 +36,10 @@ internal class DefaultUserService @Inject constructor(private val userDataSource
     }
 
     override suspend fun resolveUser(userId: String): User {
-        val known = getUser(userId)
-        if (known != null) {
-            return known
-        } else {
+        return getUser(userId) ?: run {
             val params = GetProfileInfoTask.Params(userId)
-            val data = getProfileInfoTask.execute(params)
-            return User(
-                    userId,
-                    data[ProfileService.DISPLAY_NAME_KEY] as? String,
-                    data[ProfileService.AVATAR_URL_KEY] as? String)
+            val json = getProfileInfoTask.execute(params)
+            User.fromJson(userId, json)
         }
     }
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt
index 9a9458e84bd..46ea7547b03 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/UserEntityFactory.kt
@@ -17,6 +17,7 @@
 package org.matrix.android.sdk.internal.session.user
 
 import org.matrix.android.sdk.api.session.room.model.RoomMemberContent
+import org.matrix.android.sdk.api.session.user.model.User
 import org.matrix.android.sdk.internal.database.model.UserEntity
 
 internal object UserEntityFactory {
@@ -24,8 +25,16 @@ internal object UserEntityFactory {
     fun create(userId: String, roomMember: RoomMemberContent): UserEntity {
         return UserEntity(
                 userId = userId,
-                displayName = roomMember.displayName ?: "",
-                avatarUrl = roomMember.avatarUrl ?: ""
+                displayName = roomMember.displayName.orEmpty(),
+                avatarUrl = roomMember.avatarUrl.orEmpty()
+        )
+    }
+
+    fun create(user: User): UserEntity {
+        return UserEntity(
+                userId = user.userId,
+                displayName = user.displayName.orEmpty(),
+                avatarUrl = user.avatarUrl.orEmpty()
         )
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataAPI.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataAPI.kt
index cc5625b2554..bbeff18c013 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataAPI.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/AccountDataAPI.kt
@@ -21,7 +21,7 @@ import retrofit2.http.Body
 import retrofit2.http.PUT
 import retrofit2.http.Path
 
-interface AccountDataAPI {
+internal interface AccountDataAPI {
 
     /**
      * Set some account_data for the client.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
index ddcac475ee6..59c4dd671eb 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/user/accountdata/DefaultSessionAccountDataService.kt
@@ -23,12 +23,12 @@ import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent
 import org.matrix.android.sdk.api.session.events.model.Content
 import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataEvent
 import org.matrix.android.sdk.api.util.Optional
+import org.matrix.android.sdk.api.util.awaitCallback
 import org.matrix.android.sdk.internal.di.SessionDatabase
 import org.matrix.android.sdk.internal.session.room.accountdata.RoomAccountDataDataSource
 import org.matrix.android.sdk.internal.session.sync.handler.UserAccountDataSyncHandler
 import org.matrix.android.sdk.internal.task.TaskExecutor
 import org.matrix.android.sdk.internal.task.configureWith
-import org.matrix.android.sdk.internal.util.awaitCallback
 import javax.inject.Inject
 
 internal class DefaultSessionAccountDataService @Inject constructor(
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt
index 1fa5e5f7712..10b4f7f7d7d 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/DefaultWidgetPostAPIMediator.kt
@@ -25,7 +25,6 @@ import org.matrix.android.sdk.api.util.JsonDict
 import org.matrix.android.sdk.internal.util.createUIHandler
 import timber.log.Timber
 import java.lang.reflect.Type
-import java.util.HashMap
 import javax.inject.Inject
 
 internal class DefaultWidgetPostAPIMediator @Inject constructor(private val moshi: Moshi,
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
index 9f5f91d917a..e18117d2d7b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/widgets/WidgetManager.kt
@@ -42,7 +42,6 @@ import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
 import org.matrix.android.sdk.internal.session.user.accountdata.UserAccountDataDataSource
 import org.matrix.android.sdk.internal.session.widgets.helper.WidgetFactory
 import org.matrix.android.sdk.internal.session.widgets.helper.extractWidgetSequence
-import java.util.HashMap
 import javax.inject.Inject
 
 @SessionScope
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/DefaultLightweightSettingsStorage.kt
similarity index 51%
rename from matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt
rename to matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/DefaultLightweightSettingsStorage.kt
index 069e539e2c0..284d5c99105 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/database/lightweight/LightweightSettingsStorage.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/DefaultLightweightSettingsStorage.kt
@@ -1,11 +1,11 @@
 /*
- * Copyright 2022 The Matrix.org Foundation C.I.C.
+ * Copyright (c) 2022 The Matrix.org Foundation C.I.C.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-package org.matrix.android.sdk.internal.database.lightweight
+package org.matrix.android.sdk.internal.settings
 
 import android.content.Context
 import androidx.core.content.edit
 import androidx.preference.PreferenceManager
 import org.matrix.android.sdk.api.MatrixConfiguration
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
+import org.matrix.android.sdk.internal.session.sync.SyncPresence
 import javax.inject.Inject
 
 /**
@@ -27,25 +29,46 @@ import javax.inject.Inject
  * on the sdk without using the database. This should be used just for sdk/user preferences and
  * not for large data sets
  */
-
-class LightweightSettingsStorage  @Inject constructor(
+internal class DefaultLightweightSettingsStorage @Inject constructor(
         context: Context,
         private val matrixConfiguration: MatrixConfiguration
-) {
+) : LightweightSettingsStorage {
 
     private val sdkDefaultPrefs = PreferenceManager.getDefaultSharedPreferences(context.applicationContext)
 
-    fun setThreadMessagesEnabled(enabled: Boolean) {
+    override fun setThreadMessagesEnabled(enabled: Boolean) {
         sdkDefaultPrefs.edit {
             putBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, enabled)
         }
     }
 
-    fun areThreadMessagesEnabled(): Boolean {
+    override fun areThreadMessagesEnabled(): Boolean {
         return sdkDefaultPrefs.getBoolean(MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED, matrixConfiguration.threadMessagesEnabledDefault)
     }
 
+    /**
+     * Set the presence status sent on syncs when the application is in foreground.
+     *
+     * @param presence the presence status that should be sent on sync
+     */
+    internal fun setSyncPresenceStatus(presence: SyncPresence) {
+        sdkDefaultPrefs.edit {
+            putString(MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS, presence.value)
+        }
+    }
+
+    /**
+     * Get the presence status that should be sent on syncs when the application is in foreground.
+     *
+     * @return the presence status that should be sent on sync
+     */
+    internal fun getSyncPresenceStatus(): SyncPresence {
+        val presenceString = sdkDefaultPrefs.getString(MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS, SyncPresence.Online.value)
+        return SyncPresence.from(presenceString) ?: SyncPresence.Online
+    }
+
     companion object {
         const val MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED = "MATRIX_SDK_SETTINGS_THREAD_MESSAGES_ENABLED"
+        private const val MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS = "MATRIX_SDK_SETTINGS_FOREGROUND_PRESENCE_STATUS"
     }
 }
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/SettingsModule.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/SettingsModule.kt
new file mode 100644
index 00000000000..db57f695960
--- /dev/null
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/settings/SettingsModule.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 The Matrix.org Foundation C.I.C.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.matrix.android.sdk.internal.settings
+
+import dagger.Binds
+import dagger.Module
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
+
+@Module
+internal abstract class SettingsModule {
+    @Binds
+    abstract fun bindLightweightSettingsStorage(storage: DefaultLightweightSettingsStorage): LightweightSettingsStorage
+}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
index 9c8b36a3ed0..2dd16d83750 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/BackgroundDetectionObserver.kt
@@ -20,7 +20,7 @@ import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import timber.log.Timber
 
-interface BackgroundDetectionObserver : DefaultLifecycleObserver {
+internal interface BackgroundDetectionObserver : DefaultLifecycleObserver {
     val isInBackground: Boolean
 
     fun register(listener: Listener)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt
deleted file mode 100644
index 81d601f6f0c..00000000000
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/CompatUtil.kt
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2020 The Matrix.org Foundation C.I.C.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:Suppress("DEPRECATION")
-
-package org.matrix.android.sdk.internal.util
-
-import android.content.Context
-import android.content.SharedPreferences
-import android.os.Build
-import android.preference.PreferenceManager
-import android.security.KeyPairGeneratorSpec
-import android.security.keystore.KeyGenParameterSpec
-import android.security.keystore.KeyProperties
-import android.util.Base64
-import androidx.core.content.edit
-import timber.log.Timber
-import java.io.IOException
-import java.io.InputStream
-import java.io.OutputStream
-import java.math.BigInteger
-import java.security.InvalidAlgorithmParameterException
-import java.security.InvalidKeyException
-import java.security.KeyPairGenerator
-import java.security.KeyStore
-import java.security.KeyStoreException
-import java.security.NoSuchAlgorithmException
-import java.security.NoSuchProviderException
-import java.security.PrivateKey
-import java.security.SecureRandom
-import java.security.UnrecoverableKeyException
-import java.security.cert.CertificateException
-import java.security.spec.AlgorithmParameterSpec
-import java.security.spec.RSAKeyGenParameterSpec
-import java.util.Calendar
-import javax.crypto.Cipher
-import javax.crypto.CipherInputStream
-import javax.crypto.CipherOutputStream
-import javax.crypto.IllegalBlockSizeException
-import javax.crypto.KeyGenerator
-import javax.crypto.NoSuchPaddingException
-import javax.crypto.SecretKey
-import javax.crypto.spec.GCMParameterSpec
-import javax.crypto.spec.IvParameterSpec
-import javax.crypto.spec.SecretKeySpec
-import javax.security.auth.x500.X500Principal
-
-object CompatUtil {
-    private val TAG = CompatUtil::class.java.simpleName
-    private const val ANDROID_KEY_STORE_PROVIDER = "AndroidKeyStore"
-    private const val AES_GCM_CIPHER_TYPE = "AES/GCM/NoPadding"
-    private const val AES_GCM_KEY_SIZE_IN_BITS = 128
-    private const val AES_GCM_IV_LENGTH = 12
-    private const val AES_LOCAL_PROTECTION_KEY_ALIAS = "aes_local_protection"
-
-    private const val RSA_WRAP_LOCAL_PROTECTION_KEY_ALIAS = "rsa_wrap_local_protection"
-    private const val RSA_WRAP_CIPHER_TYPE = "RSA/NONE/PKCS1Padding"
-    private const val AES_WRAPPED_PROTECTION_KEY_SHARED_PREFERENCE = "aes_wrapped_local_protection"
-
-    private const val SHARED_KEY_ANDROID_VERSION_WHEN_KEY_HAS_BEEN_GENERATED = "android_version_when_key_has_been_generated"
-
-    private var sSecretKeyAndVersion: SecretKeyAndVersion? = null
-
-    /**
-     * Returns the unique SecureRandom instance shared for all local storage encryption operations.
-     */
-    private val prng: SecureRandom by lazy(LazyThreadSafetyMode.NONE) { SecureRandom() }
-
-    /**
-     * Returns the AES key used for local storage encryption/decryption with AES/GCM.
-     * The key is created if it does not exist already in the keystore.
-     * From Marshmallow, this key is generated and operated directly from the android keystore.
-     * From KitKat and before Marshmallow, this key is stored in the application shared preferences
-     * wrapped by a RSA key generated and operated directly from the android keystore.
-     *
-     * @param context the context holding the application shared preferences
-     */
-    @Synchronized
-    @Throws(KeyStoreException::class,
-            CertificateException::class,
-            NoSuchAlgorithmException::class,
-            IOException::class,
-            NoSuchProviderException::class,
-            InvalidAlgorithmParameterException::class,
-            NoSuchPaddingException::class,
-            InvalidKeyException::class,
-            IllegalBlockSizeException::class,
-            UnrecoverableKeyException::class)
-    private fun getAesGcmLocalProtectionKey(context: Context): SecretKeyAndVersion {
-        if (sSecretKeyAndVersion == null) {
-            val keyStore = KeyStore.getInstance(ANDROID_KEY_STORE_PROVIDER)
-            keyStore.load(null)
-
-            Timber.i(TAG, "Loading local protection key")
-
-            var key: SecretKey?
-
-            val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
-            // Get the version of Android when the key has been generated, default to the current version of the system. In this case, the
-            // key will be generated
-            val androidVersionWhenTheKeyHasBeenGenerated = sharedPreferences
-                    .getInt(SHARED_KEY_ANDROID_VERSION_WHEN_KEY_HAS_BEEN_GENERATED, Build.VERSION.SDK_INT)
-
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
-                if (keyStore.containsAlias(AES_LOCAL_PROTECTION_KEY_ALIAS)) {
-                    Timber.i(TAG, "AES local protection key found in keystore")
-                    key = keyStore.getKey(AES_LOCAL_PROTECTION_KEY_ALIAS, null) as SecretKey
-                } else {
-                    // Check if a key has been created on version < M (in case of OS upgrade)
-                    key = readKeyApiL(sharedPreferences, keyStore)
-
-                    if (key == null) {
-                        Timber.i(TAG, "Generating AES key with keystore")
-                        val generator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEY_STORE_PROVIDER)
-                        generator.init(
-                                KeyGenParameterSpec.Builder(AES_LOCAL_PROTECTION_KEY_ALIAS,
-                                        KeyProperties.PURPOSE_ENCRYPT or KeyProperties.PURPOSE_DECRYPT)
-                                        .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
-                                        .setKeySize(AES_GCM_KEY_SIZE_IN_BITS)
-                                        .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
-                                        .build())
-                        key = generator.generateKey()
-
-                        sharedPreferences.edit {
-                            putInt(SHARED_KEY_ANDROID_VERSION_WHEN_KEY_HAS_BEEN_GENERATED, Build.VERSION.SDK_INT)
-                        }
-                    }
-                }
-            } else {
-                key = readKeyApiL(sharedPreferences, keyStore)
-
-                if (key == null) {
-                    Timber.i(TAG, "Generating RSA key pair with keystore")
-                    val generator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, ANDROID_KEY_STORE_PROVIDER)
-                    val start = Calendar.getInstance()
-                    val end = Calendar.getInstance()
-                    end.add(Calendar.YEAR, 10)
-
-                    generator.initialize(
-                            KeyPairGeneratorSpec.Builder(context)
-                                    .setAlgorithmParameterSpec(RSAKeyGenParameterSpec(2048, RSAKeyGenParameterSpec.F4))
-                                    .setAlias(RSA_WRAP_LOCAL_PROTECTION_KEY_ALIAS)
-                                    .setSubject(X500Principal("CN=matrix-android-sdk"))
-                                    .setStartDate(start.time)
-                                    .setEndDate(end.time)
-                                    .setSerialNumber(BigInteger.ONE)
-                                    .build())
-                    val keyPair = generator.generateKeyPair()
-
-                    Timber.i(TAG, "Generating wrapped AES key")
-
-                    val aesKeyRaw = ByteArray(AES_GCM_KEY_SIZE_IN_BITS / java.lang.Byte.SIZE)
-                    prng.nextBytes(aesKeyRaw)
-                    key = SecretKeySpec(aesKeyRaw, "AES")
-
-                    val cipher = Cipher.getInstance(RSA_WRAP_CIPHER_TYPE)
-                    cipher.init(Cipher.WRAP_MODE, keyPair.public)
-                    val wrappedAesKey = cipher.wrap(key)
-
-                    sharedPreferences.edit {
-                        putString(AES_WRAPPED_PROTECTION_KEY_SHARED_PREFERENCE, Base64.encodeToString(wrappedAesKey, 0))
-                        putInt(SHARED_KEY_ANDROID_VERSION_WHEN_KEY_HAS_BEEN_GENERATED, Build.VERSION.SDK_INT)
-                    }
-                }
-            }
-
-            sSecretKeyAndVersion = SecretKeyAndVersion(key!!, androidVersionWhenTheKeyHasBeenGenerated)
-        }
-
-        return sSecretKeyAndVersion!!
-    }
-
-    /**
-     * Read the key, which may have been stored when the OS was < M
-     *
-     * @param sharedPreferences shared pref
-     * @param keyStore          key store
-     * @return the key if it exists or null
-     */
-    @Throws(KeyStoreException::class,
-            NoSuchPaddingException::class,
-            NoSuchAlgorithmException::class,
-            InvalidKeyException::class,
-            UnrecoverableKeyException::class)
-    private fun readKeyApiL(sharedPreferences: SharedPreferences, keyStore: KeyStore): SecretKey? {
-        val wrappedAesKeyString = sharedPreferences.getString(AES_WRAPPED_PROTECTION_KEY_SHARED_PREFERENCE, null)
-        if (wrappedAesKeyString != null && keyStore.containsAlias(RSA_WRAP_LOCAL_PROTECTION_KEY_ALIAS)) {
-            Timber.i(TAG, "RSA + wrapped AES local protection keys found in keystore")
-            val privateKey = keyStore.getKey(RSA_WRAP_LOCAL_PROTECTION_KEY_ALIAS, null) as PrivateKey
-            val wrappedAesKey = Base64.decode(wrappedAesKeyString, 0)
-            val cipher = Cipher.getInstance(RSA_WRAP_CIPHER_TYPE)
-            cipher.init(Cipher.UNWRAP_MODE, privateKey)
-            return cipher.unwrap(wrappedAesKey, "AES", Cipher.SECRET_KEY) as SecretKey
-        }
-
-        // Key does not exist
-        return null
-    }
-
-    /**
-     * Create a CipherOutputStream instance.
-     * Before Kitkat, this method will return out as local storage encryption is not implemented for
-     * devices before KitKat.
-     *
-     * @param out     the output stream
-     * @param context the context holding the application shared preferences
-     */
-    @Throws(IOException::class,
-            CertificateException::class,
-            NoSuchAlgorithmException::class,
-            UnrecoverableKeyException::class,
-            InvalidKeyException::class,
-            InvalidAlgorithmParameterException::class,
-            NoSuchPaddingException::class,
-            NoSuchProviderException::class,
-            KeyStoreException::class,
-            IllegalBlockSizeException::class)
-    fun createCipherOutputStream(out: OutputStream, context: Context): OutputStream? {
-        val keyAndVersion = getAesGcmLocalProtectionKey(context)
-
-        val cipher = Cipher.getInstance(AES_GCM_CIPHER_TYPE)
-        val iv: ByteArray
-
-        if (keyAndVersion.androidVersionWhenTheKeyHasBeenGenerated >= Build.VERSION_CODES.M) {
-            cipher.init(Cipher.ENCRYPT_MODE, keyAndVersion.secretKey)
-            iv = cipher.iv
-        } else {
-            iv = ByteArray(AES_GCM_IV_LENGTH)
-            prng.nextBytes(iv)
-            cipher.init(Cipher.ENCRYPT_MODE, keyAndVersion.secretKey, IvParameterSpec(iv))
-        }
-
-        if (iv.size != AES_GCM_IV_LENGTH) {
-            Timber.e(TAG, "Invalid IV length ${iv.size}")
-            return null
-        }
-
-        out.write(iv.size)
-        out.write(iv)
-
-        return CipherOutputStream(out, cipher)
-    }
-
-    /**
-     * Create a CipherInputStream instance.
-     * Warning, if inputStream is not an encrypted stream, it's up to the caller to close and reopen inputStream, because the stream has been read.
-     *
-     * @param inputStream the input stream
-     * @param context     the context holding the application shared preferences
-     * @return inputStream, or the created InputStream, or null if the InputStream inputStream does not contain encrypted data
-     */
-    @Throws(NoSuchPaddingException::class,
-            NoSuchAlgorithmException::class,
-            CertificateException::class,
-            InvalidKeyException::class,
-            KeyStoreException::class,
-            UnrecoverableKeyException::class,
-            IllegalBlockSizeException::class,
-            NoSuchProviderException::class,
-            InvalidAlgorithmParameterException::class,
-            IOException::class)
-    fun createCipherInputStream(inputStream: InputStream, context: Context): InputStream? {
-        val ivLen = inputStream.read()
-        if (ivLen != AES_GCM_IV_LENGTH) {
-            Timber.e(TAG, "Invalid IV length $ivLen")
-            return null
-        }
-
-        val iv = ByteArray(AES_GCM_IV_LENGTH)
-        inputStream.read(iv)
-
-        val cipher = Cipher.getInstance(AES_GCM_CIPHER_TYPE)
-
-        val keyAndVersion = getAesGcmLocalProtectionKey(context)
-
-        val spec: AlgorithmParameterSpec = if (keyAndVersion.androidVersionWhenTheKeyHasBeenGenerated >= Build.VERSION_CODES.M) {
-            GCMParameterSpec(AES_GCM_KEY_SIZE_IN_BITS, iv)
-        } else {
-            IvParameterSpec(iv)
-        }
-
-        cipher.init(Cipher.DECRYPT_MODE, keyAndVersion.secretKey, spec)
-
-        return CipherInputStream(inputStream, cipher)
-    }
-}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
index fb5e3a57741..3fcf35c127c 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/FileSaver.kt
@@ -24,7 +24,7 @@ import java.io.InputStream
  * Save an input stream to a file with Okio
  */
 @WorkerThread
-fun writeToFile(inputStream: InputStream, outputFile: File) {
+internal fun writeToFile(inputStream: InputStream, outputFile: File) {
     // Ensure the parent folder exists, else it will crash
     outputFile.parentFile?.mkdirs()
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt
index a34b91a70bb..5994cbcf93f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/JsonCanonicalizer.kt
@@ -28,7 +28,7 @@ import java.util.TreeSet
  * Build canonical Json
  * Doc: https://matrix.org/docs/spec/appendices.html#canonical-json
  */
-object JsonCanonicalizer {
+internal object JsonCanonicalizer {
 
     fun  getCanonicalJson(type: Class, o: T): String {
         val adapter = MoshiProvider.providesMoshi().adapter(type)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LiveDataUtils.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LiveDataUtils.kt
deleted file mode 100644
index 80c3b832265..00000000000
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/LiveDataUtils.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2020 The Matrix.org Foundation C.I.C.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.matrix.android.sdk.internal.util
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MediatorLiveData
-
-object LiveDataUtils {
-
-    fun  combine(firstSource: LiveData,
-                                     secondSource: LiveData,
-                                     mapper: (FIRST, SECOND) -> OUT): LiveData {
-        return MediatorLiveData().apply {
-            var firstValue: FIRST? = null
-            var secondValue: SECOND? = null
-
-            val valueDispatcher = {
-                firstValue?.let { safeFirst ->
-                    secondValue?.let { safeSecond ->
-                        val mappedValue = mapper(safeFirst, safeSecond)
-                        postValue(mappedValue)
-                    }
-                }
-            }
-
-            addSource(firstSource) {
-                firstValue = it
-                valueDispatcher()
-            }
-
-            addSource(secondSource) {
-                secondValue = it
-                valueDispatcher()
-            }
-        }
-    }
-}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Monarchy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Monarchy.kt
index afe77d76d55..6152eacae55 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Monarchy.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Monarchy.kt
@@ -26,7 +26,7 @@ internal suspend fun  Monarchy.awaitTransaction(transaction: suspend (realm:
     return awaitTransaction(realmConfiguration, transaction)
 }
 
-fun  Monarchy.fetchCopied(query: (Realm) -> T?): T? {
+internal fun  Monarchy.fetchCopied(query: (Realm) -> T?): T? {
     val ref = AtomicReference()
     doWithRealm { realm ->
         val result = query.invoke(realm)?.let {
@@ -37,7 +37,7 @@ fun  Monarchy.fetchCopied(query: (Realm) -> T?): T? {
     return ref.get()
 }
 
-fun  Monarchy.fetchCopyMap(query: (Realm) -> T?, map: (T, realm: Realm) -> U): U? {
+internal fun  Monarchy.fetchCopyMap(query: (Realm) -> T?, map: (T, realm: Realm) -> U): U? {
     val ref = AtomicReference()
     doWithRealm { realm ->
         val result = query.invoke(realm)?.let {
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Normalizer.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Normalizer.kt
index 0e9c885394a..05105211277 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Normalizer.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/Normalizer.kt
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.util
 import java.text.Normalizer
 import javax.inject.Inject
 
-class Normalizer @Inject constructor() {
+internal class Normalizer @Inject constructor() {
 
     fun normalize(input: String): String {
         return Normalizer.normalize(input.lowercase(), Normalizer.Form.NFD)
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt
index 15e82f3cc0f..f22f0810a14 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/util/database/RealmMigrator.kt
@@ -20,7 +20,7 @@ import io.realm.DynamicRealm
 import io.realm.RealmObjectSchema
 import timber.log.Timber
 
-abstract class RealmMigrator(private val realm: DynamicRealm,
+internal abstract class RealmMigrator(private val realm: DynamicRealm,
                              private val targetSchemaVersion: Int) {
     fun perform() {
         Timber.d("Migrate ${realm.configuration.realmFileName} to $targetSchemaVersion")
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt
index c6c038d2d24..de36b85660f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/worker/SessionWorkerParams.kt
@@ -20,7 +20,7 @@ package org.matrix.android.sdk.internal.worker
  * Note about the Worker usage:
  * The workers we chain, or when using the append strategy, should never return Result.Failure(), else the chain will be broken forever
  */
-interface SessionWorkerParams {
+internal interface SessionWorkerParams {
     val sessionId: String
 
     /**
diff --git a/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXDeviceInfo.java b/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXDeviceInfo.java
index 1014ceda0e5..4612b8d6ff2 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXDeviceInfo.java
+++ b/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXDeviceInfo.java
@@ -20,10 +20,9 @@
 import java.util.List;
 import java.util.Map;
 
-/*
- * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
+/**
+ * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
  */
-
 public class MXDeviceInfo implements Serializable {
     private static final long serialVersionUID = 20129670646382964L;
 
diff --git a/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXOlmInboundGroupSession2.java b/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXOlmInboundGroupSession2.java
index 7277a86e9ac..c6a8c1443c2 100755
--- a/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXOlmInboundGroupSession2.java
+++ b/matrix-sdk-android/src/main/java/org/matrix/androidsdk/crypto/data/MXOlmInboundGroupSession2.java
@@ -23,11 +23,9 @@
 import java.util.List;
 import java.util.Map;
 
-/*
- * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
- */
-
 /**
+ * IMPORTANT: This class is imported from Riot-Android to be able to perform a migration. Do not use it for any other purpose
+ *
  * This class adds more context to a OLMInboundGroupSession object.
  * This allows additional checks. The class implements NSCoding so that the context can be stored.
  */
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt
index 4e4548b1972..d4c9da2986e 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/keysbackup/util/RecoveryKeyTest.kt
@@ -22,6 +22,9 @@ import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Test
 import org.matrix.android.sdk.MatrixTest
+import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.isValidRecoveryKey
 
 class RecoveryKeyTest : MatrixTest {
 
diff --git a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/HelperTest.kt b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/HelperTest.kt
index b50d0581b0c..39b3c5c731c 100644
--- a/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/HelperTest.kt
+++ b/matrix-sdk-android/src/test/java/org/matrix/android/sdk/internal/crypto/store/db/HelperTest.kt
@@ -19,7 +19,7 @@ package org.matrix.android.sdk.internal.crypto.store.db
 import org.junit.Assert.assertEquals
 import org.junit.Test
 import org.matrix.android.sdk.MatrixTest
-import org.matrix.android.sdk.internal.util.md5
+import org.matrix.android.sdk.api.util.md5
 
 class HelperTest : MatrixTest {
 
diff --git a/tools/check/check_code_quality.sh b/tools/check/check_code_quality.sh
index 9535ff9efb2..e40d3635e8a 100755
--- a/tools/check/check_code_quality.sh
+++ b/tools/check/check_code_quality.sh
@@ -66,7 +66,7 @@ echo "Search for forbidden patterns in code..."
 
 ${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_code.txt \
     ./matrix-sdk-android/src/main/java \
-    ./matrix-sdk-android-rx/src/main/java \
+    ./matrix-sdk-android-flow/src/main/java \
     ./vector/src/main/java \
     ./vector/src/debug/java \
     ./vector/src/release/java \
@@ -80,10 +80,22 @@ echo "Search for forbidden patterns specific for SDK code..."
 
 ${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_code_sdk.txt \
     ./matrix-sdk-android/src \
-    ./matrix-sdk-android-rx/src
+    ./matrix-sdk-android-flow/src
 
 resultForbiddenStringInCodeSdk=$?
 
+echo
+echo "Search for forbidden patterns specific for App code..."
+
+${searchForbiddenStringsScript} ./tools/check/forbidden_strings_in_code_app.txt \
+    ./vector/src/main/java \
+    ./vector/src/debug/java \
+    ./vector/src/release/java \
+    ./vector/src/fdroid/java \
+    ./vector/src/gplay/java
+
+resultForbiddenStringInCodeApp=$?
+
 echo
 echo "Search for forbidden patterns in resources..."
 
@@ -131,7 +143,7 @@ echo "Search for kotlin files with more than ${maxLines} lines..."
 
 ${checkLongFilesScript} ${maxLines} \
     ./matrix-sdk-android/src/main/java \
-    ./matrix-sdk-android-rx/src/main/java \
+    ./matrix-sdk-android-flow/src/main/java \
     ./vector/src/androidTest/java \
     ./vector/src/debug/java \
     ./vector/src/fdroid/java \
@@ -167,6 +179,7 @@ echo
 if [[ ${resultNbOfDrawable} -eq 0 ]] \
    && [[ ${resultForbiddenStringInCode} -eq 0 ]] \
    && [[ ${resultForbiddenStringInCodeSdk} -eq 0 ]] \
+   && [[ ${resultForbiddenStringInCodeApp} -eq 0 ]] \
    && [[ ${resultForbiddenStringInResource} -eq 0 ]] \
    && [[ ${resultForbiddenStringInLayout} -eq 0 ]] \
    && [[ ${resultLongFiles} -eq 0 ]] \
diff --git a/tools/check/forbidden_strings_in_code_app.txt b/tools/check/forbidden_strings_in_code_app.txt
new file mode 100644
index 00000000000..0715030e8f8
--- /dev/null
+++ b/tools/check/forbidden_strings_in_code_app.txt
@@ -0,0 +1,18 @@
+#
+# Copyright 2022 New Vector Ltd
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+### You should not use code from the SDK package `org.matrix.android.sdk.internal`. Either move the code to the package `org.matrix.android.sdk.api`, or add a proper API to access this code, and add `internal` keyword SDK side.
+import org.matrix.android.sdk.internal
diff --git a/tools/hs_diag.py b/tools/hs_diag.py
index 7d7a947c4c2..50f117bc8e5 100755
--- a/tools/hs_diag.py
+++ b/tools/hs_diag.py
@@ -65,6 +65,6 @@
     print("# " + item[0] + " (" + item[1] + ")")
     print("====================================================================================================")
     if item[2]:
-        os.system("curl -s -X GET '" + item[1] + "' | python -m json.tool")
+        os.system("curl -s -X GET '" + item[1] + "' | python3 -m json.tool")
     else:
-        os.system("curl -s -X POST --data $'{}' '" + item[1] + "' | python -m json.tool")
+        os.system("curl -s -X POST --data $'{}' '" + item[1] + "' | python3 -m json.tool")
diff --git a/vector-config/src/main/res/values/config-settings.xml b/vector-config/src/main/res/values/config-settings.xml
index 40fc68bbae9..b6d1c6676cd 100755
--- a/vector-config/src/main/res/values/config-settings.xml
+++ b/vector-config/src/main/res/values/config-settings.xml
@@ -28,6 +28,8 @@
 
     true
     false
+    false
+    false
 
     
 
diff --git a/vector-config/src/main/res/values/urls.xml b/vector-config/src/main/res/values/urls.xml
index 22e3a9ac721..70f5227f5f9 100644
--- a/vector-config/src/main/res/values/urls.xml
+++ b/vector-config/src/main/res/values/urls.xml
@@ -3,4 +3,5 @@
     
 
     https://element.io/help#threads
+    https://element.io/ems
 
\ No newline at end of file
diff --git a/vector/build.gradle b/vector/build.gradle
index e222012c49d..c7950da28e9 100644
--- a/vector/build.gradle
+++ b/vector/build.gradle
@@ -18,7 +18,7 @@ ext.versionMinor = 4
 // Note: even values are reserved for regular release, odd values for hotfix release.
 // When creating a hotfix, you should decrease the value, since the current value
 // is the value for the next regular release.
-ext.versionPatch = 11
+ext.versionPatch = 12
 
 static def getGitTimestamp() {
     def cmd = 'git show -s --format=%ct'
@@ -151,7 +151,6 @@ android {
 
         buildConfigField "Boolean", "enableLocationSharing", "true"
         buildConfigField "String", "mapTilerKey", "\"fU3vlMsMn4Jb6dnEIFsx\""
-        buildConfigField "Boolean", "PRESENCE_SYNC_ENABLED", "true"
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 
@@ -230,7 +229,6 @@ android {
             buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
             // Set to true if you want to enable strict mode in debug
             buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-            buildConfigField "Boolean", "ENABLE_LIVE_LOCATION_SHARING", "true"
 
             signingConfig signingConfigs.debug
         }
@@ -240,7 +238,6 @@ android {
 
             buildConfigField "boolean", "LOW_PRIVACY_LOG_ENABLE", "false"
             buildConfigField "boolean", "ENABLE_STRICT_MODE_LOGS", "false"
-            buildConfigField "Boolean", "ENABLE_LIVE_LOCATION_SHARING", "false"
 
             postprocessing {
                 removeUnusedCode true
@@ -446,7 +443,8 @@ dependencies {
     implementation 'me.leolin:ShortcutBadger:1.1.22@aar'
 
     // Chat effects
-    implementation 'nl.dionsegijn:konfetti:1.3.2'
+    implementation 'nl.dionsegijn:konfetti-xml:2.0.2'
+
     implementation 'com.github.jetradarmobile:android-snowfall:1.2.1'
     // DI
     implementation libs.dagger.hilt
diff --git a/vector/src/androidTest/java/im/vector/app/EspressoExt.kt b/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
index 28564f71151..5fb404efe3c 100644
--- a/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
+++ b/vector/src/androidTest/java/im/vector/app/EspressoExt.kt
@@ -48,9 +48,9 @@ import org.hamcrest.Matcher
 import org.hamcrest.Matchers
 import org.hamcrest.StringDescription
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.crosssigning.PrivateKeysInfo
 import org.matrix.android.sdk.api.session.sync.SyncState
 import org.matrix.android.sdk.api.util.Optional
-import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
 import java.util.concurrent.TimeoutException
 
 object EspressoHelper {
diff --git a/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt b/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt
index 34f2d4f92b5..63f14f72f6a 100644
--- a/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt
+++ b/vector/src/debug/java/im/vector/app/config/AnalyticsConfig.kt
@@ -21,7 +21,7 @@ import im.vector.app.features.analytics.AnalyticsConfig
 
 val analyticsConfig: AnalyticsConfig = object : AnalyticsConfig {
     override val isEnabled = BuildConfig.APPLICATION_ID == "im.vector.app.debug"
-    override val postHogHost = "https://posthog-poc.lab.element.dev"
-    override val postHogApiKey = "rs-pJjsYJTuAkXJfhaMmPUNBhWliDyTKLOOxike6ck8"
+    override val postHogHost = "https://posthog.element.dev"
+    override val postHogApiKey = "phc_VtA1L35nw3aeAtHIx1ayrGdzGkss7k1xINeXcoIQzXN"
     override val policyLink = "https://element.io/cookie-policy"
 }
diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
index a2b2b44ce33..cc69cfd4261 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt
@@ -49,7 +49,6 @@ import im.vector.lib.ui.styles.debug.DebugVectorButtonStylesDarkActivity
 import im.vector.lib.ui.styles.debug.DebugVectorButtonStylesLightActivity
 import im.vector.lib.ui.styles.debug.DebugVectorTextViewDarkActivity
 import im.vector.lib.ui.styles.debug.DebugVectorTextViewLightActivity
-import org.matrix.android.sdk.internal.crypto.verification.qrcode.toQrCodeData
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -251,7 +250,7 @@ class DebugMenuActivity : VectorBaseActivity() {
             // renderQrCode(QrCodeScannerActivity.getResultText(data) ?: "")
             val result = QrCodeScannerActivity.getResultText(activityResult.data)!!
 
-            val qrCodeData = result.toQrCodeData()
+            val qrCodeData = null // This is now internal: result.toQrCodeData()
             Timber.e("qrCodeData: $qrCodeData")
 
             if (result.length != buffer.size) {
@@ -265,6 +264,8 @@ class DebugMenuActivity : VectorBaseActivity() {
                     }
                 }
             }
+            // Ensure developer will see that this cannot work anymore
+            error("toQrCodeData() is now internal")
         }
     }
 }
diff --git a/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt b/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt
index 48ec44f9092..b8f89eaf88c 100644
--- a/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt
+++ b/vector/src/debug/java/im/vector/app/features/debug/settings/OverrideDropdownView.kt
@@ -24,7 +24,6 @@ import android.view.View
 import android.widget.AdapterView
 import android.widget.ArrayAdapter
 import android.widget.LinearLayout
-import im.vector.app.R
 import im.vector.app.databinding.ViewBooleanDropdownBinding
 
 class OverrideDropdownView @JvmOverloads constructor(
diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt b/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt
index c1fda2d404d..4be36d7de34 100644
--- a/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt
+++ b/vector/src/fdroid/java/im/vector/app/fdroid/receiver/AlarmSyncBroadcastReceiver.kt
@@ -27,7 +27,7 @@ import androidx.core.content.getSystemService
 import im.vector.app.core.extensions.singletonEntryPoint
 import im.vector.app.core.platform.PendingIntentCompat
 import im.vector.app.core.services.VectorSyncService
-import org.matrix.android.sdk.internal.session.sync.job.SyncService
+import org.matrix.android.sdk.api.session.sync.job.SyncService
 import timber.log.Timber
 
 class AlarmSyncBroadcastReceiver : BroadcastReceiver() {
diff --git a/vector/src/main/java/im/vector/app/AppStateHandler.kt b/vector/src/main/java/im/vector/app/AppStateHandler.kt
index 1ff3d97576f..cc3aed03fb2 100644
--- a/vector/src/main/java/im/vector/app/AppStateHandler.kt
+++ b/vector/src/main/java/im/vector/app/AppStateHandler.kt
@@ -18,9 +18,12 @@ package im.vector.app
 
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.asFlow
 import arrow.core.Option
 import im.vector.app.core.di.ActiveSessionHolder
 import im.vector.app.core.utils.BehaviorDataSource
+import im.vector.app.features.analytics.AnalyticsTracker
+import im.vector.app.features.analytics.plan.UserProperties
 import im.vector.app.features.session.coroutineScope
 import im.vector.app.features.ui.UiStateRepository
 import kotlinx.coroutines.CoroutineScope
@@ -28,12 +31,15 @@ import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.SupervisorJob
 import kotlinx.coroutines.cancelChildren
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.filterIsInstance
 import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.group.model.GroupSummary
+import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -55,7 +61,8 @@ fun RoomGroupingMethod.group() = (this as? RoomGroupingMethod.ByLegacyGroup)?.gr
 class AppStateHandler @Inject constructor(
         private val sessionDataSource: ActiveSessionDataSource,
         private val uiStateRepository: UiStateRepository,
-        private val activeSessionHolder: ActiveSessionHolder
+        private val activeSessionHolder: ActiveSessionHolder,
+        private val analyticsTracker: AnalyticsTracker
 ) : DefaultLifecycleObserver {
 
     private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
@@ -125,11 +132,23 @@ class AppStateHandler @Inject constructor(
                         } else {
                             setCurrentGroup(uiStateRepository.getSelectedGroup(session.sessionId), session)
                         }
+                        observeSyncStatus(session)
                     }
                 }
                 .launchIn(coroutineScope)
     }
 
+    private fun observeSyncStatus(session: Session) {
+        session.getSyncStatusLive()
+                .asFlow()
+                .filterIsInstance()
+                .map { session.spaceService().getRootSpaceSummaries().size }
+                .distinctUntilChanged()
+                .onEach { spacesNumber ->
+                    analyticsTracker.updateUserProperties(UserProperties(numSpaces = spacesNumber))
+                }.launchIn(session.coroutineScope)
+    }
+
     fun safeActiveSpaceId(): String? {
         return (selectedSpaceDataSource.currentValue?.orNull() as? RoomGroupingMethod.BySpace)?.spaceSummary?.roomId
     }
diff --git a/vector/src/main/java/im/vector/app/AutoRageShaker.kt b/vector/src/main/java/im/vector/app/AutoRageShaker.kt
index 43283254b10..195e2f68dcb 100644
--- a/vector/src/main/java/im/vector/app/AutoRageShaker.kt
+++ b/vector/src/main/java/im/vector/app/AutoRageShaker.kt
@@ -17,9 +17,11 @@
 package im.vector.app
 
 import android.content.SharedPreferences
+import androidx.lifecycle.asFlow
 import im.vector.app.core.di.ActiveSessionHolder
 import im.vector.app.features.rageshake.BugReporter
 import im.vector.app.features.rageshake.ReportType
+import im.vector.app.features.session.coroutineScope
 import im.vector.app.features.settings.VectorPreferences
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -34,6 +36,7 @@ import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.toContent
+import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -62,10 +65,11 @@ class AutoRageShaker @Inject constructor(
 
     private val e2eDetectedFlow = MutableSharedFlow(replay = 0)
     private val matchingRSRequestFlow = MutableSharedFlow(replay = 0)
-
+    private var hasSynced = false
+    private var preferenceEnabled = false
     fun initialize() {
         observeActiveSession()
-        enable(vectorPreferences.labsAutoReportUISI())
+        preferenceEnabled = vectorPreferences.labsAutoReportUISI()
         // It's a singleton...
         vectorPreferences.subscribeToChanges(this)
 
@@ -74,7 +78,7 @@ class AutoRageShaker @Inject constructor(
         e2eDetectedFlow
                 .onEach {
                     sendRageShake(it)
-                    delay(2_000)
+                    delay(60_000)
                 }
                 .catch { cause ->
                     Timber.w(cause, "Failed to RS")
@@ -84,7 +88,7 @@ class AutoRageShaker @Inject constructor(
         matchingRSRequestFlow
                 .onEach {
                     sendMatchingRageShake(it)
-                    delay(2_000)
+                    delay(60_000)
                 }
                 .catch { cause ->
                     Timber.w(cause, "Failed to send matching rageshake")
@@ -93,14 +97,7 @@ class AutoRageShaker @Inject constructor(
     }
 
     override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
-        enable(vectorPreferences.labsAutoReportUISI())
-    }
-
-    var _enabled = false
-    fun enable(enabled: Boolean) {
-        if (enabled == _enabled) return
-        _enabled = enabled
-        detector.enabled = enabled
+        preferenceEnabled = vectorPreferences.labsAutoReportUISI()
     }
 
     private fun observeActiveSession() {
@@ -115,7 +112,6 @@ class AutoRageShaker @Inject constructor(
     }
 
     fun decryptionErrorDetected(target: E2EMessageDetected) {
-        if (target.source == UISIEventSource.INITIAL_SYNC) return
         if (activeSessionHolder.getSafeActiveSession()?.sessionId != currentActiveSessionId) return
         val shouldSendRS = synchronized(alreadyReportedUisi) {
             val reportInfo = ReportInfo(target.roomId, target.sessionId)
@@ -148,7 +144,6 @@ class AutoRageShaker @Inject constructor(
                     append("\"room_id\": \"${target.roomId}\",")
                     append("\"sender_key\": \"${target.senderKey}\",")
                     append("\"device_id\": \"${target.senderDeviceId}\",")
-                    append("\"source\": \"${target.source}\",")
                     append("\"user_id\": \"${target.senderUserId}\",")
                     append("\"session_id\": \"${target.sessionId}\"")
                     append("}")
@@ -245,6 +240,9 @@ class AutoRageShaker @Inject constructor(
             override val reciprocateToDeviceEventType: String
                 get() = AUTO_RS_REQUEST
 
+            override val enabled: Boolean
+                get() = this@AutoRageShaker.preferenceEnabled && this@AutoRageShaker.hasSynced
+
             override fun uisiDetected(source: E2EMessageDetected) {
                 decryptionErrorDetected(source)
             }
@@ -261,7 +259,14 @@ class AutoRageShaker @Inject constructor(
             return
         }
         this.currentActiveSessionId = sessionId
-        this.detector.enabled = _enabled
+
+        hasSynced = session.hasAlreadySynced()
+        session.getSyncStatusLive()
+                .asFlow()
+                .onEach {
+                    hasSynced = it !is SyncStatusService.Status.InitialSyncProgressing
+                }
+                .launchIn(session.coroutineScope)
         activeSessionIds.add(sessionId)
         session.addListener(this)
         session.addEventStreamListener(detector)
diff --git a/vector/src/main/java/im/vector/app/UISIDetector.kt b/vector/src/main/java/im/vector/app/UISIDetector.kt
index d6a4805e787..61575377437 100644
--- a/vector/src/main/java/im/vector/app/UISIDetector.kt
+++ b/vector/src/main/java/im/vector/app/UISIDetector.kt
@@ -16,33 +16,28 @@
 
 package im.vector.app
 
+import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.LiveEventListener
 import org.matrix.android.sdk.api.session.events.model.Event
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.util.JsonDict
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
 import timber.log.Timber
 import java.util.Timer
 import java.util.TimerTask
 import java.util.concurrent.Executors
 
-enum class UISIEventSource {
-    INITIAL_SYNC,
-    INCREMENTAL_SYNC,
-    PAGINATION
-}
-
 data class E2EMessageDetected(
         val eventId: String,
         val roomId: String,
         val senderUserId: String,
         val senderDeviceId: String,
         val senderKey: String,
-        val sessionId: String,
-        val source: UISIEventSource) {
+        val sessionId: String
+        ) {
 
     companion object {
-        fun fromEvent(event: Event, roomId: String, source: UISIEventSource): E2EMessageDetected {
+        fun fromEvent(event: Event, roomId: String): E2EMessageDetected {
             val encryptedContent = event.content.toModel()
 
             return E2EMessageDetected(
@@ -51,8 +46,7 @@ data class E2EMessageDetected(
                     senderUserId = event.senderId ?: "",
                     senderDeviceId = encryptedContent?.deviceId ?: "",
                     senderKey = encryptedContent?.senderKey ?: "",
-                    sessionId = encryptedContent?.sessionId ?: "",
-                    source = source
+                    sessionId = encryptedContent?.sessionId ?: ""
             )
         }
     }
@@ -61,6 +55,7 @@ data class E2EMessageDetected(
 class UISIDetector : LiveEventListener {
 
     interface UISIDetectorCallback {
+        val enabled: Boolean
         val reciprocateToDeviceEventType: String
         fun uisiDetected(source: E2EMessageDetected)
         fun uisiReciprocateRequest(source: Event)
@@ -68,30 +63,16 @@ class UISIDetector : LiveEventListener {
 
     var callback: UISIDetectorCallback? = null
 
-    private val trackedEvents = mutableListOf>()
+    private val trackedEvents = mutableMapOf()
     private val executor = Executors.newSingleThreadExecutor()
     private val timer = Timer()
     private val timeoutMillis = 30_000L
-    var enabled = false
-
-    override fun onLiveEvent(roomId: String, event: Event) {
-        if (!enabled) return
-        if (!event.isEncrypted()) return
-        executor.execute {
-            handleEventReceived(E2EMessageDetected.fromEvent(event, roomId, UISIEventSource.INCREMENTAL_SYNC))
-        }
-    }
+    private val enabled: Boolean get() = callback?.enabled.orFalse()
 
-    override fun onPaginatedEvent(roomId: String, event: Event) {
-        if (!enabled) return
-        if (!event.isEncrypted()) return
-        executor.execute {
-            handleEventReceived(E2EMessageDetected.fromEvent(event, roomId, UISIEventSource.PAGINATION))
-        }
-    }
-
-    override fun onEventDecrypted(eventId: String, roomId: String, clearEvent: JsonDict) {
-        if (!enabled) return
+    override fun onEventDecrypted(event: Event, clearEvent: JsonDict) {
+        val eventId = event.eventId
+        val roomId = event.roomId
+        if (!enabled || eventId == null || roomId == null) return
         executor.execute {
             unTrack(eventId, roomId)
         }
@@ -104,57 +85,43 @@ class UISIDetector : LiveEventListener {
         }
     }
 
-    override fun onEventDecryptionError(eventId: String, roomId: String, throwable: Throwable) {
-        if (!enabled) return
-        executor.execute {
-            unTrack(eventId, roomId)?.let {
-                triggerUISI(it)
-            }
-//            if (throwable is MXCryptoError.OlmError) {
-//                if (throwable.olmException.message == "UNKNOWN_MESSAGE_INDEX") {
-//                    unTrack(eventId, roomId)?.let {
-//                        triggerUISI(it)
-//                    }
-//                }
-//            }
-        }
-    }
+    override fun onEventDecryptionError(event: Event, throwable: Throwable) {
+        val eventId = event.eventId
+        val roomId = event.roomId
+        if (!enabled || eventId == null || roomId == null) return
 
-    private fun handleEventReceived(detectorEvent: E2EMessageDetected) {
-        if (!enabled) return
-        if (trackedEvents.any { it.first == detectorEvent }) {
-            Timber.w("## UISIDetector: Event ${detectorEvent.eventId} is already tracked")
-        } else {
-            // track it and start timer
-            val timeoutTask = object : TimerTask() {
-                override fun run() {
-                    executor.execute {
-                        unTrack(detectorEvent.eventId, detectorEvent.roomId)
-                        Timber.v("## UISIDetector: Timeout on ${detectorEvent.eventId} ")
-                        triggerUISI(detectorEvent)
-                    }
+        val trackerId: String = trackerId(eventId, roomId)
+        if (trackedEvents.containsKey(trackerId)) {
+            Timber.w("## UISIDetector: Event $eventId is already tracked")
+            return
+        }
+        // track it and start timer
+        val timeoutTask = object : TimerTask() {
+            override fun run() {
+                executor.execute {
+                    unTrack(eventId, roomId)
+                    Timber.v("## UISIDetector: Timeout on $eventId")
+                    triggerUISI(E2EMessageDetected.fromEvent(event, roomId))
                 }
             }
-            trackedEvents.add(detectorEvent to timeoutTask)
-            timer.schedule(timeoutTask, timeoutMillis)
         }
+        trackedEvents[trackerId] = timeoutTask
+        timer.schedule(timeoutTask, timeoutMillis)
     }
 
+    override fun onLiveEvent(roomId: String, event: Event) { }
+
+    override fun onPaginatedEvent(roomId: String, event: Event) { }
+
+    private fun trackerId(eventId: String, roomId: String): String = "$roomId-$eventId"
+
     private fun triggerUISI(source: E2EMessageDetected) {
         if (!enabled) return
         Timber.i("## UISIDetector: Unable To Decrypt $source")
         callback?.uisiDetected(source)
     }
 
-    private fun unTrack(eventId: String, roomId: String): E2EMessageDetected? {
-        val index = trackedEvents.indexOfFirst { it.first.eventId == eventId && it.first.roomId == roomId }
-        return if (index != -1) {
-            trackedEvents.removeAt(index).let {
-                it.second.cancel()
-                it.first
-            }
-        } else {
-            null
-        }
+    private fun unTrack(eventId: String, roomId: String) {
+        trackedEvents.remove(trackerId(eventId, roomId))?.cancel()
     }
 }
diff --git a/vector/src/main/java/im/vector/app/VectorApplication.kt b/vector/src/main/java/im/vector/app/VectorApplication.kt
index a3f4ffcfcd5..e12eecfefc6 100644
--- a/vector/src/main/java/im/vector/app/VectorApplication.kt
+++ b/vector/src/main/java/im/vector/app/VectorApplication.kt
@@ -230,13 +230,13 @@ class VectorApplication :
         val sdkVersion = Matrix.getSdkVersion()
         val date = SimpleDateFormat("MM-dd HH:mm:ss.SSSZ", Locale.US).format(Date())
 
-        Timber.v("----------------------------------------------------------------")
-        Timber.v("----------------------------------------------------------------")
-        Timber.v(" Application version: $appVersion")
-        Timber.v(" SDK version: $sdkVersion")
-        Timber.v(" Local time: $date")
-        Timber.v("----------------------------------------------------------------")
-        Timber.v("----------------------------------------------------------------\n\n\n\n")
+        Timber.d("----------------------------------------------------------------")
+        Timber.d("----------------------------------------------------------------")
+        Timber.d(" Application version: $appVersion")
+        Timber.d(" SDK version: $sdkVersion")
+        Timber.d(" Local time: $date")
+        Timber.d("----------------------------------------------------------------")
+        Timber.d("----------------------------------------------------------------\n\n\n\n")
     }
 
     override fun attachBaseContext(base: Context) {
diff --git a/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt b/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt
index 22764ac5bd9..882891810b3 100644
--- a/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt
+++ b/vector/src/main/java/im/vector/app/core/animations/Konfetti.kt
@@ -20,9 +20,14 @@ import android.content.Context
 import androidx.annotation.ColorInt
 import androidx.core.content.ContextCompat
 import im.vector.app.R
-import nl.dionsegijn.konfetti.KonfettiView
-import nl.dionsegijn.konfetti.models.Shape
-import nl.dionsegijn.konfetti.models.Size
+import nl.dionsegijn.konfetti.core.Angle
+import nl.dionsegijn.konfetti.core.Party
+import nl.dionsegijn.konfetti.core.Position
+import nl.dionsegijn.konfetti.core.Spread
+import nl.dionsegijn.konfetti.core.emitter.Emitter
+import nl.dionsegijn.konfetti.core.models.Shape
+import nl.dionsegijn.konfetti.core.models.Size
+import nl.dionsegijn.konfetti.xml.KonfettiView
 
 fun KonfettiView.play() {
     val confettiColors = listOf(
@@ -35,16 +40,22 @@ fun KonfettiView.play() {
             R.color.palette_prune,
             R.color.palette_kiwi
     )
-    build()
-            .addColors(confettiColors.toColorInt(context))
-            .setDirection(0.0, 359.0)
-            .setSpeed(2f, 5f)
-            .setFadeOutEnabled(true)
-            .setTimeToLive(2000L)
-            .addShapes(Shape.Square, Shape.Circle)
-            .addSizes(Size(12))
-            .setPosition(-50f, width + 50f, -50f, -50f)
-            .streamFor(150, 3000L)
+    val emitterConfig = Emitter(2000).perSecond(100)
+    val party = Party(
+            emitter = emitterConfig,
+            colors = confettiColors.toColorInt(context),
+            angle = Angle.Companion.BOTTOM,
+            spread = Spread.ROUND,
+            shapes = listOf(Shape.Square, Shape.Circle),
+            size = listOf(Size(12)),
+            speed = 2f,
+            maxSpeed = 5f,
+            fadeOutEnabled = true,
+            timeToLive = 2000L,
+            position = Position.Relative(0.0, 0.0).between(Position.Relative(1.0, 0.0)),
+    )
+    reset()
+    start(party)
 }
 
 @ColorInt
diff --git a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
index 4dcfbe16f81..e3e64063f32 100644
--- a/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/FragmentModule.kt
@@ -102,6 +102,7 @@ import im.vector.app.features.onboarding.ftueauth.FtueAuthCaptchaFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthChooseDisplayNameFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthChooseProfilePictureFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthGenericTextInputFormFragment
+import im.vector.app.features.onboarding.ftueauth.FtueAuthLegacyStyleCaptchaFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthLoginFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthPersonalizationCompleteFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthResetPasswordFragment
@@ -114,6 +115,7 @@ import im.vector.app.features.onboarding.ftueauth.FtueAuthSplashFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthUseCaseFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthWaitForEmailFragment
 import im.vector.app.features.onboarding.ftueauth.FtueAuthWebFragment
+import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthLegacyStyleTermsFragment
 import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragment
 import im.vector.app.features.pin.PinFragment
 import im.vector.app.features.poll.create.CreatePollFragment
@@ -407,6 +409,11 @@ interface FragmentModule {
     @FragmentKey(LoginWaitForEmailFragment2::class)
     fun bindLoginWaitForEmailFragment2(fragment: LoginWaitForEmailFragment2): Fragment
 
+    @Binds
+    @IntoMap
+    @FragmentKey(FtueAuthLegacyStyleCaptchaFragment::class)
+    fun bindFtueAuthLegacyStyleCaptchaFragment(fragment: FtueAuthLegacyStyleCaptchaFragment): Fragment
+
     @Binds
     @IntoMap
     @FragmentKey(FtueAuthCaptchaFragment::class)
@@ -472,6 +479,11 @@ interface FragmentModule {
     @FragmentKey(FtueAuthWebFragment::class)
     fun bindFtueAuthWebFragment(fragment: FtueAuthWebFragment): Fragment
 
+    @Binds
+    @IntoMap
+    @FragmentKey(FtueAuthLegacyStyleTermsFragment::class)
+    fun bindFtueAuthLegacyStyleTermsFragment(fragment: FtueAuthLegacyStyleTermsFragment): Fragment
+
     @Binds
     @IntoMap
     @FragmentKey(FtueAuthTermsFragment::class)
diff --git a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
index fdd6e3c2ba4..0db7e4e8ea6 100644
--- a/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
+++ b/vector/src/main/java/im/vector/app/core/di/SingletonModule.kt
@@ -60,6 +60,7 @@ import org.matrix.android.sdk.api.auth.HomeServerHistoryService
 import org.matrix.android.sdk.api.legacy.LegacySessionImporter
 import org.matrix.android.sdk.api.raw.RawService
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import javax.inject.Singleton
 
 @InstallIn(SingletonComponent::class)
@@ -121,7 +122,6 @@ object VectorStaticModule {
                 applicationFlavor = BuildConfig.FLAVOR_DESCRIPTION,
                 roomDisplayNameFallbackProvider = vectorRoomDisplayNameFallbackProvider,
                 threadMessagesEnabledDefault = vectorPreferences.areThreadMessagesEnabled(),
-                presenceSyncEnabled = BuildConfig.PRESENCE_SYNC_ENABLED
         )
     }
 
@@ -152,6 +152,11 @@ object VectorStaticModule {
         return matrix.rawService()
     }
 
+    @Provides
+    fun providesLightweightSettingsStorage(matrix: Matrix): LightweightSettingsStorage {
+        return matrix.lightweightSettingsStorage()
+    }
+
     @Provides
     fun providesHomeServerHistoryService(matrix: Matrix): HomeServerHistoryService {
         return matrix.homeServerHistoryService()
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
index 9e318bf6931..f3923fc4e0f 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/ManuallyVerifyDialog.kt
@@ -21,7 +21,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import im.vector.app.R
 import im.vector.app.databinding.DialogDeviceVerifyBinding
 import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable
-import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
 
 object ManuallyVerifyDialog {
 
diff --git a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
index f46737d6c62..415c82b3308 100644
--- a/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
+++ b/vector/src/main/java/im/vector/app/core/dialogs/UnrecognizedCertificateDialog.kt
@@ -21,10 +21,8 @@ import im.vector.app.R
 import im.vector.app.core.di.ActiveSessionHolder
 import im.vector.app.core.resources.StringProvider
 import im.vector.app.databinding.DialogSslFingerprintBinding
-import org.matrix.android.sdk.internal.network.ssl.Fingerprint
+import org.matrix.android.sdk.api.network.ssl.Fingerprint
 import timber.log.Timber
-import java.util.HashMap
-import java.util.HashSet
 import javax.inject.Inject
 
 /**
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt
index 14ba34cc52c..b90956ad9e5 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/bottomsheet/BottomSheetMessagePreviewItem.kt
@@ -33,7 +33,7 @@ import im.vector.app.core.extensions.setTextOrHide
 import im.vector.app.core.glide.GlideApp
 import im.vector.app.features.displayname.getBestName
 import im.vector.app.features.home.AvatarRenderer
-import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
+import im.vector.app.features.home.room.detail.timeline.action.LocationUiData
 import im.vector.app.features.home.room.detail.timeline.item.BindingOptions
 import im.vector.app.features.home.room.detail.timeline.tools.findPillsAndProcess
 import im.vector.app.features.media.ImageContentRenderer
@@ -71,13 +71,7 @@ abstract class BottomSheetMessagePreviewItem : VectorEpoxyModel
             GlideApp.with(holder.staticMapImageView)
-                    .load(locationUrl)
+                    .load(safeLocationUiData.locationUrl)
                     .apply(RequestOptions.centerCropTransform())
                     .into(holder.staticMapImageView)
 
-            locationPinProvider?.create(locationOwnerId) { pinDrawable ->
+            safeLocationUiData.locationPinProvider.create(safeLocationUiData.locationOwnerId) { pinDrawable ->
                 GlideApp.with(holder.staticMapPinImageView)
                         .load(pinDrawable)
                         .into(holder.staticMapPinImageView)
diff --git a/vector/src/main/java/im/vector/app/core/epoxy/profiles/BaseProfileMatrixItem.kt b/vector/src/main/java/im/vector/app/core/epoxy/profiles/BaseProfileMatrixItem.kt
index e4b6124e19b..956e1de92cf 100644
--- a/vector/src/main/java/im/vector/app/core/epoxy/profiles/BaseProfileMatrixItem.kt
+++ b/vector/src/main/java/im/vector/app/core/epoxy/profiles/BaseProfileMatrixItem.kt
@@ -25,7 +25,7 @@ import im.vector.app.core.epoxy.onClick
 import im.vector.app.core.extensions.setTextOrHide
 import im.vector.app.features.displayname.getBestName
 import im.vector.app.features.home.AvatarRenderer
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import org.matrix.android.sdk.api.util.MatrixItem
 
 abstract class BaseProfileMatrixItem : VectorEpoxyModel() {
diff --git a/vector/src/main/java/im/vector/app/core/extensions/Collections.kt b/vector/src/main/java/im/vector/app/core/extensions/Collections.kt
index 5168915c9ce..d48875983dd 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/Collections.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/Collections.kt
@@ -18,3 +18,5 @@ package im.vector.app.core.extensions
 
 inline fun  List.nextOrNull(index: Int) = getOrNull(index + 1)
 inline fun  List.prevOrNull(index: Int) = getOrNull(index - 1)
+
+fun  List.containsAllItems(vararg items: T) = this.containsAll(items.toList())
diff --git a/vector/src/main/java/im/vector/app/core/extensions/ResultExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/ResultExtensions.kt
new file mode 100644
index 00000000000..bb2e9070ca5
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/extensions/ResultExtensions.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.extensions
+
+@Suppress("UNCHECKED_CAST") // We're casting null failure results to R
+inline fun  Result.andThen(block: (T) -> Result): Result {
+    return when (val result = getOrNull()) {
+        null -> this as Result
+        else -> block(result)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt b/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt
index 5037f78445c..749da0d9878 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/UrlExtensions.kt
@@ -19,8 +19,8 @@ package im.vector.app.core.extensions
 /**
  * Ex: "https://matrix.org/" -> "matrix.org"
  */
-fun String?.toReducedUrl(): String {
+fun String?.toReducedUrl(keepSchema: Boolean = false): String {
     return (this ?: "")
-            .substringAfter("://")
+            .run { if (keepSchema) this else substringAfter("://") }
             .trim { it == '/' }
 }
diff --git a/vector/src/main/java/im/vector/app/core/extensions/View.kt b/vector/src/main/java/im/vector/app/core/extensions/View.kt
index 7ec86d35085..4b21063f0b5 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/View.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/View.kt
@@ -32,3 +32,12 @@ fun View.showKeyboard(andRequestFocus: Boolean = false) {
     val imm = context?.getSystemService()
     imm?.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT)
 }
+
+fun View.setHorizontalPadding(padding: Int) {
+    setPadding(
+            padding,
+            paddingTop,
+            padding,
+            paddingBottom
+    )
+}
diff --git a/vector/src/main/java/im/vector/app/core/glide/ElementToDecryptOption.kt b/vector/src/main/java/im/vector/app/core/glide/ElementToDecryptOption.kt
index 1888012450b..f4f854406e0 100644
--- a/vector/src/main/java/im/vector/app/core/glide/ElementToDecryptOption.kt
+++ b/vector/src/main/java/im/vector/app/core/glide/ElementToDecryptOption.kt
@@ -17,7 +17,7 @@
 package im.vector.app.core.glide
 
 import com.bumptech.glide.load.Option
-import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
+import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt
 
 const val ElementToDecryptOptionKey = "im.vector.app.core.glide.ElementToDecrypt"
 
diff --git a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
index 8621c28d579..5dbea8dcc46 100644
--- a/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
+++ b/vector/src/main/java/im/vector/app/core/services/VectorSyncService.kt
@@ -36,7 +36,7 @@ import im.vector.app.core.platform.PendingIntentCompat
 import im.vector.app.features.notifications.NotificationUtils
 import im.vector.app.features.settings.BackgroundSyncMode
 import org.matrix.android.sdk.api.Matrix
-import org.matrix.android.sdk.internal.session.sync.job.SyncService
+import org.matrix.android.sdk.api.session.sync.job.SyncService
 import timber.log.Timber
 import javax.inject.Inject
 
diff --git a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
index 713c1770994..a82a9a30b4e 100644
--- a/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
+++ b/vector/src/main/java/im/vector/app/core/ui/views/ShieldImageView.kt
@@ -22,7 +22,7 @@ import androidx.annotation.DrawableRes
 import androidx.appcompat.widget.AppCompatImageView
 import androidx.core.view.isVisible
 import im.vector.app.R
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 
 class ShieldImageView @JvmOverloads constructor(
         context: Context,
diff --git a/vector/src/main/java/im/vector/app/core/utils/LiveData.kt b/vector/src/main/java/im/vector/app/core/utils/LiveData.kt
new file mode 100644
index 00000000000..922fd462359
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/utils/LiveData.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.utils
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MediatorLiveData
+
+fun  combineLatest(source1: LiveData, source2: LiveData, mapper: (T1, T2) -> R): LiveData {
+    val combined = MediatorLiveData()
+    var source1Result: T1? = null
+    var source2Result: T2? = null
+
+    fun notify() {
+        if (source1Result != null && source2Result != null) {
+            combined.value = mapper(source1Result!!, source2Result!!)
+        }
+    }
+
+    combined.addSource(source1) {
+        source1Result = it
+        notify()
+    }
+    combined.addSource(source2) {
+        source2Result = it
+        notify()
+    }
+    return combined
+}
diff --git a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
index 992fa4d5a59..b2a62a42d3d 100644
--- a/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
+++ b/vector/src/main/java/im/vector/app/features/VectorFeatures.kt
@@ -42,5 +42,5 @@ class DefaultVectorFeatures : VectorFeatures {
     override fun isOnboardingUseCaseEnabled() = true
     override fun isOnboardingPersonalizeEnabled() = false
     override fun isOnboardingCombinedRegisterEnabled() = false
-    override fun isLiveLocationEnabled(): Boolean = BuildConfig.ENABLE_LIVE_LOCATION_SHARING
+    override fun isLiveLocationEnabled(): Boolean = false
 }
diff --git a/vector/src/main/java/im/vector/app/features/analytics/plan/Signup.kt b/vector/src/main/java/im/vector/app/features/analytics/plan/Signup.kt
new file mode 100644
index 00000000000..328340fd2fd
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/analytics/plan/Signup.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.analytics.plan
+
+import im.vector.app.features.analytics.itf.VectorAnalyticsEvent
+
+// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
+// https://github.com/matrix-org/matrix-analytics-events/
+
+/**
+ * Triggered once onboarding has completed, but only if the user registered a
+ * new account.
+ */
+data class Signup(
+        /**
+         * The type of authentication that was used to sign up.
+         */
+        val authenticationType: AuthenticationType,
+) : VectorAnalyticsEvent {
+
+    enum class AuthenticationType {
+        /**
+         * Social login using Apple.
+         */
+        Apple,
+
+        /**
+         * Social login using Facebook.
+         */
+        Facebook,
+
+        /**
+         * Social login using GitHub.
+         */
+        GitHub,
+
+        /**
+         * Social login using GitLab.
+         */
+        GitLab,
+
+        /**
+         * Social login using Google.
+         */
+        Google,
+
+        /**
+         * Registration using some other mechanism such as fallback.
+         */
+        Other,
+
+        /**
+         * Registration with a username and password.
+         */
+        Password,
+
+        /**
+         * Registration using another SSO provider.
+         */
+        SSO,
+    }
+
+    override fun getName() = "Signup"
+
+    override fun getProperties(): Map? {
+        return mutableMapOf().apply {
+            put("authenticationType", authenticationType.name)
+        }.takeIf { it.isNotEmpty() }
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
index 7fcbb6bae6f..98440632d80 100644
--- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
+++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt
@@ -41,6 +41,7 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_FOREGROUND_LOCATION_SHARING
 import im.vector.app.core.utils.PERMISSIONS_FOR_PICKING_CONTACT
 import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
 import im.vector.app.databinding.ViewAttachmentTypeSelectorBinding
+import im.vector.app.features.attachments.AttachmentTypeSelectorView.Callback
 import kotlin.math.max
 
 private const val ANIMATION_DURATION = 250
diff --git a/vector/src/main/java/im/vector/app/features/auth/ReAuthViewModel.kt b/vector/src/main/java/im/vector/app/features/auth/ReAuthViewModel.kt
index 830fd4e79d8..fcc2a59ef86 100644
--- a/vector/src/main/java/im/vector/app/features/auth/ReAuthViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/auth/ReAuthViewModel.kt
@@ -25,7 +25,7 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
 import im.vector.app.core.platform.VectorViewModel
 import org.matrix.android.sdk.api.auth.data.LoginFlowTypes
 import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
+import org.matrix.android.sdk.api.util.toBase64NoPadding
 import java.io.ByteArrayOutputStream
 
 class ReAuthViewModel @AssistedInject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
index 449a740cf34..b9bf578daad 100644
--- a/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/VectorCallViewModel.kt
@@ -16,7 +16,6 @@
 
 package im.vector.app.features.call
 
-import androidx.lifecycle.viewModelScope
 import com.airbnb.mvrx.Fail
 import com.airbnb.mvrx.Loading
 import com.airbnb.mvrx.MavericksViewModelFactory
diff --git a/vector/src/main/java/im/vector/app/features/call/audio/API21AudioDeviceDetector.kt b/vector/src/main/java/im/vector/app/features/call/audio/API21AudioDeviceDetector.kt
index eafd1eab203..15d213e017d 100644
--- a/vector/src/main/java/im/vector/app/features/call/audio/API21AudioDeviceDetector.kt
+++ b/vector/src/main/java/im/vector/app/features/call/audio/API21AudioDeviceDetector.kt
@@ -27,7 +27,6 @@ import im.vector.app.core.services.BluetoothHeadsetReceiver
 import im.vector.app.core.services.WiredHeadsetStateReceiver
 import org.matrix.android.sdk.api.logger.LoggerTag
 import timber.log.Timber
-import java.util.HashSet
 
 private val loggerTag = LoggerTag("API21AudioDeviceDetector", LoggerTag.VOIP)
 
diff --git a/vector/src/main/java/im/vector/app/features/call/audio/API23AudioDeviceDetector.kt b/vector/src/main/java/im/vector/app/features/call/audio/API23AudioDeviceDetector.kt
index fb17338fd13..7e12987a6b0 100644
--- a/vector/src/main/java/im/vector/app/features/call/audio/API23AudioDeviceDetector.kt
+++ b/vector/src/main/java/im/vector/app/features/call/audio/API23AudioDeviceDetector.kt
@@ -21,7 +21,6 @@ import android.media.AudioManager
 import android.os.Build
 import androidx.annotation.RequiresApi
 import timber.log.Timber
-import java.util.HashSet
 
 @RequiresApi(Build.VERSION_CODES.M)
 internal class API23AudioDeviceDetector(private val audioManager: AudioManager,
diff --git a/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt b/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt
index f4f56f98443..d4793640d3e 100644
--- a/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt
+++ b/vector/src/main/java/im/vector/app/features/call/audio/CallAudioManager.kt
@@ -25,7 +25,6 @@ import androidx.core.content.getSystemService
 import im.vector.app.R
 import org.matrix.android.sdk.api.extensions.orFalse
 import timber.log.Timber
-import java.util.HashSet
 import java.util.concurrent.Executors
 
 class CallAudioManager(private val context: Context, val configChange: (() -> Unit)?) {
diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
index f0b7b75afb4..0ea380734d8 100644
--- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiCallViewModel.kt
@@ -17,7 +17,6 @@
 package im.vector.app.features.call.conference
 
 import androidx.lifecycle.asFlow
-import androidx.lifecycle.viewModelScope
 import com.airbnb.mvrx.Fail
 import com.airbnb.mvrx.MavericksViewModelFactory
 import com.airbnb.mvrx.Success
diff --git a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt
index b691296ba32..6fa65bdb7f6 100644
--- a/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt
+++ b/vector/src/main/java/im/vector/app/features/call/conference/JitsiService.kt
@@ -33,9 +33,9 @@ import org.matrix.android.sdk.api.raw.RawService
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.widgets.model.Widget
 import org.matrix.android.sdk.api.session.widgets.model.WidgetType
+import org.matrix.android.sdk.api.util.MatrixJsonParser
 import org.matrix.android.sdk.api.util.appendParamToUrl
 import org.matrix.android.sdk.api.util.toMatrixItem
-import org.matrix.android.sdk.internal.di.MoshiProvider
 import java.net.URL
 import java.util.UUID
 import javax.inject.Inject
@@ -168,7 +168,7 @@ class JitsiService @Inject constructor(
         return tryOrNull {
             val response = session.getOkHttpClient().newCall(request).await()
             val json = response.body?.string() ?: return null
-            MoshiProvider.providesMoshi().adapter(JitsiWellKnown::class.java).fromJson(json)?.auth
+            MatrixJsonParser.getMoshi().adapter(JitsiWellKnown::class.java).fromJson(json)?.auth
         }
     }
 }
diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
index b10353be130..81173568b5e 100644
--- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt
@@ -70,7 +70,6 @@ class CallTransferActivity : VectorBaseActivity() {
         }.attach()
         setupToolbar(views.callTransferToolbar)
                 .allowBack()
-        views.callTransferToolbar.title = getString(R.string.call_transfer_title)
         setupConnectAction()
     }
 
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
index 50c85c3e5f4..9b1d29fa251 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keys/KeysImporter.kt
@@ -23,7 +23,7 @@ import im.vector.app.core.resources.openResource
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.withContext
 import org.matrix.android.sdk.api.session.Session
-import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
+import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
 import javax.inject.Inject
 
 class KeysImporter @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
index 8362a3566e5..cf684680ba7 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/restore/KeysBackupRestoreSharedViewModel.kt
@@ -29,13 +29,15 @@ import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.listeners.StepProgressListener
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
 import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult
-import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
-import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
-import org.matrix.android.sdk.internal.util.awaitCallback
+import org.matrix.android.sdk.api.util.awaitCallback
+import org.matrix.android.sdk.api.util.fromBase64
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -117,9 +119,9 @@ class KeysBackupRestoreSharedViewModel @Inject constructor(
 
         viewModelScope.launch(Dispatchers.IO) {
             try {
-                val version = awaitCallback {
+                val version = awaitCallback {
                     keysBackup.getCurrentVersion(it)
-                }
+                }.toKeysVersionResult()
                 if (version?.version == null) {
                     loadingEvent.postValue(null)
                     _keyVersionResultError.postValue(LiveEvent(stringProvider.getString(R.string.keys_backup_get_version_error, "")))
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt
index 438b502b428..7c1105277b0 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingViewState.kt
@@ -20,8 +20,8 @@ import com.airbnb.mvrx.Async
 import com.airbnb.mvrx.MavericksState
 import com.airbnb.mvrx.Uninitialized
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
 
 data class KeysBackupSettingViewState(val keysBackupVersionTrust: Async = Uninitialized,
                                       val keysBackupState: KeysBackupState? = null,
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
index 3c922e63097..9bf8050939c 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsRecyclerViewController.kt
@@ -31,7 +31,7 @@ import im.vector.app.features.settings.VectorPreferences
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
 import java.util.UUID
 import javax.inject.Inject
 
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
index d6d9e106690..ca6edf0941c 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/settings/KeysBackupSettingsViewModel.kt
@@ -33,7 +33,7 @@ import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupStateListener
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.KeysBackupVersionTrust
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupVersionTrust
 
 class KeysBackupSettingsViewModel @AssistedInject constructor(@Assisted initialState: KeysBackupSettingViewState,
                                                               session: Session
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
index 1141886689a..34aa7ba0ee2 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysbackup/setup/KeysBackupSetupSharedViewModel.kt
@@ -26,10 +26,11 @@ import im.vector.app.core.utils.LiveEvent
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.listeners.ProgressListener
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
 import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupService
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
+import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
+import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -150,9 +151,9 @@ class KeysBackupSetupSharedViewModel @Inject constructor() : ViewModel() {
 
         creatingBackupError.value = null
 
-        keysBackup.getCurrentVersion(object : MatrixCallback {
-            override fun onSuccess(data: KeysVersionResult?) {
-                if (data?.version.isNullOrBlank() || forceOverride) {
+        keysBackup.getCurrentVersion(object : MatrixCallback {
+            override fun onSuccess(data: KeysBackupLastVersionResult) {
+                if (data.toKeysVersionResult()?.version.isNullOrBlank() || forceOverride) {
                     processOnCreate()
                 } else {
                     loadingStatus.value = null
diff --git a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt
index 85250a94ce7..0fbb18e63ca 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/keysrequest/KeyRequestHandler.kt
@@ -24,18 +24,18 @@ import im.vector.app.features.popup.DefaultVectorAlert
 import im.vector.app.features.popup.PopupAlertManager
 import org.matrix.android.sdk.api.MatrixCallback
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel
 import org.matrix.android.sdk.api.session.crypto.keyshare.GossipingRequestListener
+import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.IncomingRequestCancellation
+import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest
+import org.matrix.android.sdk.api.session.crypto.model.IncomingSecretShareRequest
+import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
 import org.matrix.android.sdk.api.session.crypto.verification.SasVerificationTransaction
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
-import org.matrix.android.sdk.internal.crypto.IncomingRequestCancellation
-import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest
-import org.matrix.android.sdk.internal.crypto.IncomingSecretShareRequest
-import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel
-import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
-import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
-import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
diff --git a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
index d324a52242a..51d8b3a8d5a 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/quads/SharedSecureStorageViewModel.kt
@@ -41,8 +41,8 @@ import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.securestorage.IntegrityResult
 import org.matrix.android.sdk.api.session.securestorage.KeyInfoResult
 import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
+import org.matrix.android.sdk.api.util.toBase64NoPadding
 import org.matrix.android.sdk.flow.flow
-import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
 import timber.log.Timber
 import java.io.ByteArrayOutputStream
 
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt
index 74bab9b0b63..1767a9444d1 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BackupToQuadSMigrationTask.kt
@@ -24,15 +24,14 @@ import org.matrix.android.sdk.api.NoOpMatrixCallback
 import org.matrix.android.sdk.api.listeners.ProgressListener
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
 import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
 import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
 import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
 import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
-import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
-import org.matrix.android.sdk.internal.crypto.keysbackup.deriveKey
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
-import org.matrix.android.sdk.internal.util.awaitCallback
+import org.matrix.android.sdk.api.util.awaitCallback
+import org.matrix.android.sdk.api.util.toBase64NoPadding
 import timber.log.Timber
 import java.util.UUID
 import javax.inject.Inject
@@ -72,14 +71,18 @@ class BackupToQuadSMigrationTask @Inject constructor(
                         extractCurveKeyFromRecoveryKey(params.recoveryKey)
                     } else if (!params.passphrase.isNullOrEmpty() && version.getAuthDataAsMegolmBackupAuthData()?.privateKeySalt != null) {
                         version.getAuthDataAsMegolmBackupAuthData()?.let { authData ->
-                            deriveKey(params.passphrase, authData.privateKeySalt!!, authData.privateKeyIterations!!, object : ProgressListener {
-                                override fun onProgress(progress: Int, total: Int) {
-                                    params.progressListener?.onProgress(WaitingViewData(
-                                            stringProvider.getString(R.string.bootstrap_progress_checking_backup_with_info,
-                                                    "$progress/$total")
-                                    ))
-                                }
-                            })
+                            keysBackupService.computePrivateKey(
+                                    params.passphrase,
+                                    authData.privateKeySalt!!,
+                                    authData.privateKeyIterations!!,
+                                    object : ProgressListener {
+                                        override fun onProgress(progress: Int, total: Int) {
+                                            params.progressListener?.onProgress(WaitingViewData(
+                                                    stringProvider.getString(R.string.bootstrap_progress_checking_backup_with_info,
+                                                            "$progress/$total")
+                                            ))
+                                        }
+                                    })
                         }
                     } else null)
                             ?: return Result.IllegalParams
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt
index cc863346aa6..f65999b9452 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapCrossSigningTask.kt
@@ -28,16 +28,17 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_S
 import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersion
+import org.matrix.android.sdk.api.session.crypto.keysbackup.MegolmBackupCreationInfo
+import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
 import org.matrix.android.sdk.api.session.securestorage.EmptyKeySigner
 import org.matrix.android.sdk.api.session.securestorage.SharedSecretStorageService
 import org.matrix.android.sdk.api.session.securestorage.SsssKeyCreationInfo
 import org.matrix.android.sdk.api.session.securestorage.SsssKeySpec
-import org.matrix.android.sdk.internal.crypto.crosssigning.toBase64NoPadding
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersion
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
-import org.matrix.android.sdk.internal.util.awaitCallback
+import org.matrix.android.sdk.api.util.awaitCallback
+import org.matrix.android.sdk.api.util.toBase64NoPadding
 import timber.log.Timber
 import java.util.UUID
 import javax.inject.Inject
@@ -221,10 +222,9 @@ class BootstrapCrossSigningTask @Inject constructor(
             Timber.d("## BootstrapCrossSigningTask: Creating 4S - Checking megolm backup")
 
             // First ensure that in sync
-            var serverVersion = awaitCallback {
+            var serverVersion = awaitCallback {
                 session.cryptoService().keysBackupService().getCurrentVersion(it)
-            }
-
+            }.toKeysVersionResult()
             val knownMegolmSecret = session.cryptoService().keysBackupService().getKeyBackupRecoveryKeyInfo()
             val isMegolmBackupSecretKnown = knownMegolmSecret != null && knownMegolmSecret.version == serverVersion?.version
             val shouldCreateKeyBackup = serverVersion == null ||
@@ -236,9 +236,9 @@ class BootstrapCrossSigningTask @Inject constructor(
                     awaitCallback {
                         session.cryptoService().keysBackupService().deleteBackup(serverVersion!!.version, it)
                     }
-                    serverVersion = awaitCallback {
+                    serverVersion = awaitCallback {
                         session.cryptoService().keysBackupService().getCurrentVersion(it)
-                    }
+                    }.toKeysVersionResult()
                 }
 
                 Timber.d("## BootstrapCrossSigningTask: Creating 4S - Create megolm backup")
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt
index 429d51857c0..2c0ccec9fbf 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapMigrateBackupFragment.kt
@@ -42,7 +42,7 @@ import im.vector.lib.core.utils.flow.throttleFirst
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import org.matrix.android.sdk.api.extensions.tryOrNull
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.isValidRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.isValidRecoveryKey
 import reactivecircus.flowbinding.android.widget.editorActionEvents
 import reactivecircus.flowbinding.android.widget.textChanges
 import javax.inject.Inject
diff --git a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
index 8b8a8faaef1..1b69b3a919b 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/recover/BootstrapSharedViewModel.kt
@@ -43,12 +43,14 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
 import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
 import org.matrix.android.sdk.api.failure.Failure
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.extractCurveKeyFromRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
 import org.matrix.android.sdk.api.session.securestorage.RawBytesKeySpec
-import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.extractCurveKeyFromRecoveryKey
-import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth
-import org.matrix.android.sdk.internal.util.awaitCallback
+import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth
+import org.matrix.android.sdk.api.util.awaitCallback
+import org.matrix.android.sdk.api.util.fromBase64
 import java.io.OutputStream
 import kotlin.coroutines.Continuation
 import kotlin.coroutines.resume
@@ -103,9 +105,9 @@ class BootstrapSharedViewModel @AssistedInject constructor(
 
                 // We need to check if there is an existing backup
                 viewModelScope.launch(Dispatchers.IO) {
-                    val version = awaitCallback {
+                    val version = awaitCallback {
                         session.cryptoService().keysBackupService().getCurrentVersion(it)
-                    }
+                    }.toKeysVersionResult()
                     if (version == null) {
                         // we just resume plain bootstrap
                         doesKeyBackupExist = false
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
index f48279a86e5..18a1363d718 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheet.kt
@@ -48,12 +48,12 @@ import im.vector.app.features.displayname.getBestName
 import im.vector.app.features.home.AvatarRenderer
 import im.vector.app.features.settings.VectorSettingsActivity
 import kotlinx.parcelize.Parcelize
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
 import timber.log.Timber
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
index 2495ae4ea5b..b389a831da5 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/VerificationBottomSheetViewModel.kt
@@ -38,6 +38,11 @@ import org.matrix.android.sdk.api.session.crypto.crosssigning.KEYBACKUP_SECRET_S
 import org.matrix.android.sdk.api.session.crypto.crosssigning.MASTER_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.SELF_SIGNING_KEY_SSSS_NAME
 import org.matrix.android.sdk.api.session.crypto.crosssigning.USER_SIGNING_KEY_SSSS_NAME
+import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified
+import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupLastVersionResult
+import org.matrix.android.sdk.api.session.crypto.keysbackup.computeRecoveryKey
+import org.matrix.android.sdk.api.session.crypto.keysbackup.toKeysVersionResult
+import org.matrix.android.sdk.api.session.crypto.model.ImportRoomKeysResult
 import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
 import org.matrix.android.sdk.api.session.crypto.verification.IncomingSasVerificationTransaction
 import org.matrix.android.sdk.api.session.crypto.verification.PendingVerificationRequest
@@ -49,13 +54,9 @@ import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransa
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState
 import org.matrix.android.sdk.api.session.events.model.LocalEcho
 import org.matrix.android.sdk.api.util.MatrixItem
+import org.matrix.android.sdk.api.util.awaitCallback
+import org.matrix.android.sdk.api.util.fromBase64
 import org.matrix.android.sdk.api.util.toMatrixItem
-import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64
-import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified
-import org.matrix.android.sdk.internal.crypto.keysbackup.model.rest.KeysVersionResult
-import org.matrix.android.sdk.internal.crypto.keysbackup.util.computeRecoveryKey
-import org.matrix.android.sdk.internal.crypto.model.ImportRoomKeysResult
-import org.matrix.android.sdk.internal.util.awaitCallback
 import timber.log.Timber
 
 data class VerificationBottomSheetViewState(
@@ -426,9 +427,9 @@ class VerificationBottomSheetViewModel @AssistedInject constructor(
                     Timber.v("## Keybackup secret not restored from SSSS")
                 }
 
-                val version = awaitCallback {
+                val version = awaitCallback {
                     session.cryptoService().keysBackupService().getCurrentVersion(it)
-                } ?: return@launch
+                }.toKeysVersionResult() ?: return@launch
 
                 awaitCallback {
                     session.cryptoService().keysBackupService().restoreKeysWithRecoveryKey(
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
index 1d6dfbd947a..ee77444b2e6 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/conclusion/VerificationConclusionController.kt
@@ -26,7 +26,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationB
 import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem
 import im.vector.app.features.html.EventHtmlRenderer
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import javax.inject.Inject
 
 class VerificationConclusionController @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationBigImageItem.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationBigImageItem.kt
index b15f857c3ad..adf3e8f7e5c 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationBigImageItem.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/epoxy/BottomSheetVerificationBigImageItem.kt
@@ -22,7 +22,7 @@ import im.vector.app.R
 import im.vector.app.core.epoxy.VectorEpoxyHolder
 import im.vector.app.core.epoxy.VectorEpoxyModel
 import im.vector.app.core.ui.views.ShieldImageView
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 
 /**
  * A action for bottom sheet.
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt
index 8de5f94ec96..1ae0da603a8 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQRWaitingController.kt
@@ -24,7 +24,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationB
 import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem
 import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationWaitingItem
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import javax.inject.Inject
 
 class VerificationQRWaitingController @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
index 38f29622d0c..71d64b99bc3 100644
--- a/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
+++ b/vector/src/main/java/im/vector/app/features/crypto/verification/qrconfirmation/VerificationQrScannedByOtherController.kt
@@ -27,7 +27,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationB
 import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationNoticeItem
 import im.vector.app.features.displayname.getBestName
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import javax.inject.Inject
 
 class VerificationQrScannedByOtherController @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt
index c3524e2cdff..c13ef2f81c5 100644
--- a/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/devtools/RoomDevToolViewModel.kt
@@ -38,8 +38,8 @@ import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageContent
 import org.matrix.android.sdk.api.util.JsonDict
+import org.matrix.android.sdk.api.util.MatrixJsonParser
 import org.matrix.android.sdk.flow.flow
-import org.matrix.android.sdk.internal.di.MoshiProvider
 
 class RoomDevToolViewModel @AssistedInject constructor(
         @Assisted val initialState: RoomDevToolViewState,
@@ -75,7 +75,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
                 }
             }
             is RoomDevToolAction.ShowStateEvent            -> {
-                val jsonString = MoshiProvider.providesMoshi()
+                val jsonString = MatrixJsonParser.getMoshi()
                         .adapter(Event::class.java)
                         .toJson(action.event)
 
@@ -168,7 +168,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
                 val room = session.getRoom(initialState.roomId)
                         ?: throw IllegalArgumentException(stringProvider.getString(R.string.room_error_not_found))
 
-                val adapter = MoshiProvider.providesMoshi()
+                val adapter = MatrixJsonParser.getMoshi()
                         .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java))
                 val json = adapter.fromJson(state.editedContent ?: "")
                         ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_content))
@@ -202,7 +202,7 @@ class RoomDevToolViewModel @AssistedInject constructor(
                 val room = session.getRoom(initialState.roomId)
                         ?: throw IllegalArgumentException(stringProvider.getString(R.string.room_error_not_found))
 
-                val adapter = MoshiProvider.providesMoshi()
+                val adapter = MatrixJsonParser.getMoshi()
                         .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java))
                 val json = adapter.fromJson(state.sendEventDraft?.content ?: "")
                         ?: throw IllegalArgumentException(stringProvider.getString(R.string.dev_tools_error_no_content))
diff --git a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt
index 24d675695b1..904b1526616 100644
--- a/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt
+++ b/vector/src/main/java/im/vector/app/features/discovery/Extensions.kt
@@ -18,8 +18,8 @@ package im.vector.app.features.discovery
 
 import im.vector.app.core.utils.ensureProtocol
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.terms.TermsResponse
 import org.matrix.android.sdk.api.session.terms.TermsService
-import org.matrix.android.sdk.internal.session.terms.TermsResponse
 
 suspend fun Session.fetchIdentityServerWithTerms(userLanguage: String): ServerAndPolicies? {
     return identityService().getCurrentIdentityServerUrl()
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
index 009edcc69ea..7a8dcf2634c 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt
@@ -79,9 +79,9 @@ import kotlinx.coroutines.launch
 import kotlinx.parcelize.Parcelize
 import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import org.matrix.android.sdk.api.session.permalinks.PermalinkService
+import org.matrix.android.sdk.api.session.sync.InitialSyncStrategy
+import org.matrix.android.sdk.api.session.sync.initialSyncStrategy
 import org.matrix.android.sdk.api.util.MatrixItem
-import org.matrix.android.sdk.internal.session.sync.InitialSyncStrategy
-import org.matrix.android.sdk.internal.session.sync.initialSyncStrategy
 import timber.log.Timber
 import javax.inject.Inject
 
@@ -352,7 +352,7 @@ class HomeActivity :
 
     private fun renderState(state: HomeActivityViewState) {
         when (val status = state.syncStatusServiceStatus) {
-            is SyncStatusService.Status.Progressing -> {
+            is SyncStatusService.Status.InitialSyncProgressing -> {
                 val initSyncStepStr = initSyncStepFormatter.format(status.initSyncStep)
                 Timber.v("$initSyncStepStr ${status.percentProgress}")
                 views.waitingView.root.setOnClickListener {
@@ -580,7 +580,7 @@ class HomeActivity :
     }
 
     override fun spaceInviteBottomSheetOnAccept(spaceId: String) {
-        navigator.switchToSpace(this, spaceId, Navigator.PostSwitchSpaceAction.None)
+        navigator.switchToSpace(this, spaceId, Navigator.PostSwitchSpaceAction.OpenRoomList)
     }
 
     override fun spaceInviteBottomSheetOnDecline(spaceId: String) {
@@ -613,6 +613,6 @@ class HomeActivity :
     }
 
     override fun mxToBottomSheetSwitchToSpace(spaceId: String) {
-        navigator.switchToSpace(this, spaceId, Navigator.PostSwitchSpaceAction.None)
+        navigator.switchToSpace(this, spaceId, Navigator.PostSwitchSpaceAction.OpenRoomList)
     }
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
index 87de0a32e3d..c8b0fa024ef 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeActivityViewModel.kt
@@ -43,15 +43,15 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse
 import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage
 import org.matrix.android.sdk.api.extensions.tryOrNull
 import org.matrix.android.sdk.api.pushrules.RuleIds
+import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo
+import org.matrix.android.sdk.api.session.crypto.model.MXUsersDevicesMap
 import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
+import org.matrix.android.sdk.api.util.awaitCallback
 import org.matrix.android.sdk.api.util.toMatrixItem
 import org.matrix.android.sdk.flow.flow
-import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
-import org.matrix.android.sdk.internal.crypto.model.MXUsersDevicesMap
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
-import org.matrix.android.sdk.internal.util.awaitCallback
 import timber.log.Timber
 import kotlin.coroutines.Continuation
 import kotlin.coroutines.resume
@@ -179,11 +179,11 @@ class HomeActivityViewModel @AssistedInject constructor(
                 .asFlow()
                 .onEach { status ->
                     when (status) {
-                        is SyncStatusService.Status.Progressing -> {
+                        is SyncStatusService.Status.InitialSyncProgressing -> {
                             // Schedule a check of the bootstrap when the init sync will be finished
                             checkBootstrap = true
                         }
-                        is SyncStatusService.Status.Idle        -> {
+                        is SyncStatusService.Status.Idle                   -> {
                             if (checkBootstrap) {
                                 checkBootstrap = false
                                 maybeBootstrapCrossSigningAfterInitialSync()
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
index b0527582014..f3973e5d4c1 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailFragment.kt
@@ -55,9 +55,9 @@ import im.vector.app.features.settings.VectorSettingsActivity.Companion.EXTRA_DI
 import im.vector.app.features.themes.ThemeUtils
 import im.vector.app.features.workers.signout.BannerState
 import im.vector.app.features.workers.signout.ServerBackupStatusViewModel
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
 import org.matrix.android.sdk.api.session.group.model.GroupSummary
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
-import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
 import javax.inject.Inject
 
 class HomeDetailFragment @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
index e70e7b8acb9..2457dd0eaa5 100644
--- a/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/HomeDetailViewModel.kt
@@ -48,13 +48,13 @@ import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.query.ActiveSpaceFilter
 import org.matrix.android.sdk.api.query.RoomCategoryFilter
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.NewSessionListener
 import org.matrix.android.sdk.api.session.initsync.SyncStatusService
 import org.matrix.android.sdk.api.session.room.RoomSortOrder
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams
 import org.matrix.android.sdk.api.util.toMatrixItem
 import org.matrix.android.sdk.flow.flow
-import org.matrix.android.sdk.internal.crypto.NewSessionListener
 import timber.log.Timber
 
 /**
diff --git a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
index 8a36a4c19e7..08b528f25a2 100644
--- a/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/UnknownDeviceDetectorSharedViewModel.kt
@@ -38,10 +38,10 @@ import kotlinx.coroutines.flow.sample
 import org.matrix.android.sdk.api.NoOpMatrixCallback
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo
 import org.matrix.android.sdk.api.util.MatrixItem
 import org.matrix.android.sdk.api.util.toMatrixItem
 import org.matrix.android.sdk.flow.flow
-import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
 import timber.log.Timber
 
 data class UnknownDevicesState(
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
index d10b363519b..f6ea8b76ef7 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailAction.kt
@@ -111,4 +111,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
 
     // Poll
     data class EndPoll(val eventId: String) : RoomDetailAction()
+
+    // Live Location
+    object StopLiveLocationSharing : RoomDetailAction()
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt
index aa4ee825dc3..5784e6e2646 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailActivity.kt
@@ -38,7 +38,7 @@ import im.vector.app.databinding.ActivityRoomDetailBinding
 import im.vector.app.features.analytics.plan.MobileScreen
 import im.vector.app.features.home.room.breadcrumbs.BreadcrumbsFragment
 import im.vector.app.features.home.room.detail.arguments.TimelineArgs
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.matrixto.MatrixToBottomSheet
 import im.vector.app.features.navigation.Navigator
 import im.vector.app.features.room.RequireActiveMembershipAction
@@ -75,7 +75,7 @@ class RoomDetailActivity :
     }
 
     private var lastKnownPlayingOrRecordingState: Boolean? = null
-    private val playbackActivityListener = VoiceMessagePlaybackTracker.ActivityListener { isPlayingOrRecording ->
+    private val playbackActivityListener = AudioMessagePlaybackTracker.ActivityListener { isPlayingOrRecording ->
         if (lastKnownPlayingOrRecordingState == isPlayingOrRecording) return@ActivityListener
         when (isPlayingOrRecording) {
             true  -> keepScreenOn()
@@ -86,7 +86,7 @@ class RoomDetailActivity :
 
     override fun getCoordinatorLayout() = views.coordinatorLayout
 
-    @Inject lateinit var playbackTracker: VoiceMessagePlaybackTracker
+    @Inject lateinit var playbackTracker: AudioMessagePlaybackTracker
     private lateinit var sharedActionViewModel: RoomDetailSharedActionViewModel
     private val requireActiveMembershipViewModel: RequireActiveMembershipViewModel by viewModel()
 
@@ -152,7 +152,7 @@ class RoomDetailActivity :
     override fun onDestroy() {
         supportFragmentManager.unregisterFragmentLifecycleCallbacks(fragmentLifecycleCallbacks)
         views.drawerLayout.removeDrawerListener(drawerListener)
-        playbackTracker.unTrackActivity(playbackActivityListener)
+        playbackTracker.untrackActivity(playbackActivityListener)
         super.onDestroy()
     }
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
index 118c529574e..f36a1141b8b 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewEvents.kt
@@ -20,9 +20,9 @@ import android.net.Uri
 import android.view.View
 import im.vector.app.core.platform.VectorViewEvents
 import im.vector.app.features.call.webrtc.WebRtcCall
+import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
 import org.matrix.android.sdk.api.session.widgets.model.Widget
 import org.matrix.android.sdk.api.util.MatrixItem
-import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
 import java.io.File
 
 /**
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt
index 09b52112463..0c56d7e7ebb 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailViewState.kt
@@ -36,7 +36,7 @@ sealed class UnreadState {
     object Unknown : UnreadState()
     object HasNoUnread : UnreadState()
     data class ReadMarkerNotLoaded(val readMarkerId: String) : UnreadState()
-    data class HasUnread(val firstUnreadEventId: String) : UnreadState()
+    data class HasUnread(val firstUnreadEventId: String, val readMarkerId: String) : UnreadState()
 }
 
 data class JitsiState(
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
index a903b87669a..32f0e46eac4 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt
@@ -119,6 +119,8 @@ import im.vector.app.core.utils.startInstallFromSourceIntent
 import im.vector.app.core.utils.toast
 import im.vector.app.databinding.DialogReportContentBinding
 import im.vector.app.databinding.FragmentTimelineBinding
+import im.vector.app.features.MainActivity
+import im.vector.app.features.MainActivityArgs
 import im.vector.app.features.analytics.extensions.toAnalyticsInteraction
 import im.vector.app.features.analytics.plan.Interaction
 import im.vector.app.features.analytics.plan.MobileScreen
@@ -136,6 +138,7 @@ import im.vector.app.features.call.conference.ConferenceEventObserver
 import im.vector.app.features.call.conference.JitsiCallViewModel
 import im.vector.app.features.call.webrtc.WebRtcCallManager
 import im.vector.app.features.command.Command
+import im.vector.app.features.command.ParsedCommand
 import im.vector.app.features.crypto.keysbackup.restore.KeysBackupRestoreActivity
 import im.vector.app.features.crypto.verification.VerificationBottomSheet
 import im.vector.app.features.home.AvatarRenderer
@@ -156,10 +159,11 @@ import im.vector.app.features.home.room.detail.timeline.action.EventSharedAction
 import im.vector.app.features.home.room.detail.timeline.action.MessageActionsBottomSheet
 import im.vector.app.features.home.room.detail.timeline.action.MessageSharedActionViewModel
 import im.vector.app.features.home.room.detail.timeline.edithistory.ViewEditHistoryBottomSheet
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.image.buildImageContentRendererData
 import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
+import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem
 import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem
 import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem
 import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
@@ -209,10 +213,11 @@ import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 import org.billcarsonfr.jsonviewer.JSonViewerDialog
 import org.commonmark.parser.Parser
-import org.matrix.android.sdk.api.MatrixConfiguration
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
+import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
@@ -236,8 +241,6 @@ import org.matrix.android.sdk.api.session.widgets.model.WidgetType
 import org.matrix.android.sdk.api.util.MatrixItem
 import org.matrix.android.sdk.api.util.MimeTypes
 import org.matrix.android.sdk.api.util.toMatrixItem
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
-import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
 import reactivecircus.flowbinding.android.view.focusChanges
 import reactivecircus.flowbinding.android.widget.textChanges
 import timber.log.Timber
@@ -264,9 +267,8 @@ class TimelineFragment @Inject constructor(
         private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
         private val pillsPostProcessorFactory: PillsPostProcessor.Factory,
         private val callManager: WebRtcCallManager,
-        private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
-        private val clock: Clock,
-        private val matrixConfiguration: MatrixConfiguration
+        private val audioMessagePlaybackTracker: AudioMessagePlaybackTracker,
+        private val clock: Clock
 ) :
         VectorBaseFragment(),
         TimelineEventController.Callback,
@@ -386,6 +388,7 @@ class TimelineFragment @Inject constructor(
         setupEmojiButton()
         setupRemoveJitsiWidgetView()
         setupVoiceMessageView()
+        setupLiveLocationIndicator()
 
         views.includeRoomToolbar.roomToolbarContentView.debouncedClicks {
             navigator.openRoomProfile(requireActivity(), timelineArgs.roomId)
@@ -438,6 +441,7 @@ class TimelineFragment @Inject constructor(
         messageComposerViewModel.observeViewEvents {
             when (it) {
                 is MessageComposerViewEvents.JoinRoomCommandSuccess          -> handleJoinedToAnotherRoom(it)
+                is MessageComposerViewEvents.SlashCommandConfirmationRequest -> handleSlashCommandConfirmationRequest(it)
                 is MessageComposerViewEvents.SendMessageResult               -> renderSendMessageResult(it)
                 is MessageComposerViewEvents.ShowMessage                     -> showSnackWithMessage(it.message)
                 is MessageComposerViewEvents.ShowRoomUpgradeDialog           -> handleShowRoomUpgradeDialog(it)
@@ -496,6 +500,25 @@ class TimelineFragment @Inject constructor(
         }
     }
 
+    private fun handleSlashCommandConfirmationRequest(action: MessageComposerViewEvents.SlashCommandConfirmationRequest) {
+        when (action.parsedCommand) {
+            is ParsedCommand.UnignoreUser -> promptUnignoreUser(action.parsedCommand)
+            else                          -> TODO("Add case for ${action.parsedCommand.javaClass.simpleName}")
+        }
+        lockSendButton = false
+    }
+
+    private fun promptUnignoreUser(command: ParsedCommand.UnignoreUser) {
+        MaterialAlertDialogBuilder(requireActivity())
+                .setTitle(R.string.room_participants_action_unignore_title)
+                .setMessage(getString(R.string.settings_unignore_user, command.userId))
+                .setPositiveButton(R.string.unignore) { _, _ ->
+                    messageComposerViewModel.handle(MessageComposerAction.SlashCommandConfirmed(command))
+                }
+                .setNegativeButton(R.string.action_cancel, null)
+                .show()
+    }
+
     private fun renderVoiceMessageMode(content: String) {
         ContentAttachmentData.fromJsonString(content)?.let { audioAttachmentData ->
             views.voiceMessageRecorderView.isVisible = true
@@ -737,7 +760,7 @@ class TimelineFragment @Inject constructor(
     }
 
     private fun setupVoiceMessageView() {
-        voiceMessagePlaybackTracker.track(VoiceMessagePlaybackTracker.RECORDING_ID, views.voiceMessageRecorderView)
+        audioMessagePlaybackTracker.track(AudioMessagePlaybackTracker.RECORDING_ID, views.voiceMessageRecorderView)
         views.voiceMessageRecorderView.callback = object : VoiceMessageRecorderView.Callback {
 
             override fun onVoiceRecordingStarted() {
@@ -794,13 +817,13 @@ class TimelineFragment @Inject constructor(
 
             override fun onVoiceWaveformTouchedUp(percentage: Float, duration: Int) {
                 messageComposerViewModel.handle(
-                        MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
+                        MessageComposerAction.VoiceWaveformTouchedUp(AudioMessagePlaybackTracker.RECORDING_ID, duration, percentage)
                 )
             }
 
             override fun onVoiceWaveformMoved(percentage: Float, duration: Int) {
                 messageComposerViewModel.handle(
-                        MessageComposerAction.VoiceWaveformTouchedUp(VoiceMessagePlaybackTracker.RECORDING_ID, duration, percentage)
+                        MessageComposerAction.VoiceWaveformTouchedUp(AudioMessagePlaybackTracker.RECORDING_ID, duration, percentage)
                 )
             }
 
@@ -811,6 +834,12 @@ class TimelineFragment @Inject constructor(
         }
     }
 
+    private fun setupLiveLocationIndicator() {
+        views.locationLiveStatusIndicator.stopButton.debouncedClicks {
+            timelineViewModel.handle(RoomDetailAction.StopLiveLocationSharing)
+        }
+    }
+
     private fun joinJitsiRoom(jitsiWidget: Widget, enableVideo: Boolean) {
         navigator.openRoomWidget(requireContext(), timelineArgs.roomId, jitsiWidget, mapOf(JitsiCallViewModel.ENABLE_VIDEO_OPTION to enableVideo))
     }
@@ -908,6 +937,7 @@ class TimelineFragment @Inject constructor(
     }
 
     override fun onDestroyView() {
+        audioMessagePlaybackTracker.makeAllPlaybacksIdle()
         lazyLoadedViews.unBind()
         timelineEventController.callback = null
         timelineEventController.removeModelBuildListener(modelBuildListener)
@@ -1202,13 +1232,10 @@ class TimelineFragment @Inject constructor(
         }
 
         val messageContent: MessageContent? = event.getLastMessageContent()
-        val nonFormattedBody = if (messageContent is MessageAudioContent && messageContent.voiceMessageIndicator != null) {
-            val formattedDuration = DateUtils.formatElapsedTime(((messageContent.audioInfo?.duration ?: 0) / 1000).toLong())
-            getString(R.string.voice_message_reply_content, formattedDuration)
-        } else if (messageContent is MessagePollContent) {
-            messageContent.getBestPollCreationInfo()?.question?.getBestQuestion()
-        } else {
-            messageContent?.body ?: ""
+        val nonFormattedBody = when (messageContent) {
+            is MessageAudioContent -> getAudioContentBodyText(messageContent)
+            is MessagePollContent  -> messageContent.getBestPollCreationInfo()?.question?.getBestQuestion()
+            else                   -> messageContent?.body.orEmpty()
         }
         var formattedBody: CharSequence? = null
         if (messageContent is MessageTextContent && messageContent.format == MessageFormat.FORMAT_MATRIX_HTML) {
@@ -1247,6 +1274,15 @@ class TimelineFragment @Inject constructor(
         focusComposerAndShowKeyboard()
     }
 
+    private fun getAudioContentBodyText(messageContent: MessageAudioContent): String {
+        val formattedDuration = DateUtils.formatElapsedTime(((messageContent.audioInfo?.duration ?: 0) / 1000).toLong())
+        return if (messageContent.voiceMessageIndicator != null) {
+            getString(R.string.voice_message_reply_content, formattedDuration)
+        } else {
+            getString(R.string.audio_message_reply_content, messageContent.body, formattedDuration)
+        }
+    }
+
     override fun onResume() {
         super.onResume()
         notificationDrawerManager.setCurrentRoom(timelineArgs.roomId)
@@ -1271,7 +1307,7 @@ class TimelineFragment @Inject constructor(
     override fun onPause() {
         super.onPause()
         notificationDrawerManager.setCurrentRoom(null)
-        voiceMessagePlaybackTracker.unTrack(VoiceMessagePlaybackTracker.RECORDING_ID)
+        audioMessagePlaybackTracker.pauseAllPlaybacks()
 
         if (withState(messageComposerViewModel) { it.isVoiceRecording } && requireActivity().isChangingConfigurations) {
             // we're rotating, maintain any active recordings
@@ -1399,6 +1435,7 @@ class TimelineFragment @Inject constructor(
                     }
                     return when (model) {
                         is MessageFileItem,
+                        is MessageAudioItem,
                         is MessageVoiceItem,
                         is MessageImageVideoItem,
                         is MessageTextItem -> {
@@ -1641,7 +1678,7 @@ class TimelineFragment @Inject constructor(
                 views.includeRoomToolbar.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
                 views.includeRoomToolbar.roomToolbarTitleView.text = roomSummary.displayName
                 avatarRenderer.render(roomSummary.toMatrixItem(), views.includeRoomToolbar.roomToolbarAvatarImageView)
-                val showPresence = roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled
+                val showPresence = roomSummary.isDirect
                 views.includeRoomToolbar.roomToolbarPresenceImageView.render(showPresence, roomSummary.directUserPresence)
                 val shieldView = if (showPresence) views.includeRoomToolbar.roomToolbarTitleShield else views.includeRoomToolbar.roomToolbarAvatarShield
                 shieldView.render(roomSummary.roomEncryptionTrustLevel)
@@ -1672,9 +1709,7 @@ class TimelineFragment @Inject constructor(
                 displayCommandError(getString(R.string.unrecognized_command, sendMessageResult.command))
             }
             is MessageComposerViewEvents.SlashCommandResultOk              -> {
-                dismissLoadingDialog()
-                views.composerLayout.setTextIfDifferent("")
-                sendMessageResult.messageRes?.let { showSnackWithMessage(getString(it)) }
+                handleSlashCommandResultOk(sendMessageResult.parsedCommand)
             }
             is MessageComposerViewEvents.SlashCommandResultError           -> {
                 dismissLoadingDialog()
@@ -1691,6 +1726,21 @@ class TimelineFragment @Inject constructor(
         lockSendButton = false
     }
 
+    private fun handleSlashCommandResultOk(parsedCommand: ParsedCommand) {
+        dismissLoadingDialog()
+        views.composerLayout.setTextIfDifferent("")
+        when (parsedCommand) {
+            is ParsedCommand.SetMarkdown  -> {
+                showSnackWithMessage(getString(if (parsedCommand.enable) R.string.markdown_has_been_enabled else R.string.markdown_has_been_disabled))
+            }
+            is ParsedCommand.UnignoreUser -> {
+                // A user has been un-ignored, perform a initial sync
+                MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true))
+            }
+            else                          -> Unit
+        }
+    }
+
     private fun displayCommandError(message: String) {
         MaterialAlertDialogBuilder(requireActivity())
                 .setTitle(R.string.command_error)
@@ -2088,6 +2138,10 @@ class TimelineFragment @Inject constructor(
         messageComposerViewModel.handle(MessageComposerAction.VoiceWaveformMovedTo(eventId, duration, percentage))
     }
 
+    override fun onAudioSeekBarMovedTo(eventId: String, duration: Int, percentage: Float) {
+        messageComposerViewModel.handle(MessageComposerAction.AudioSeekBarMovedTo(eventId, duration, percentage))
+    }
+
     private fun onShareActionClicked(action: EventSharedAction.Share) {
         when (action.messageContent) {
             is MessageTextContent           -> shareText(requireContext(), action.messageContent.body)
@@ -2400,23 +2454,23 @@ class TimelineFragment @Inject constructor(
     }
 
     private fun displayThreadsBetaOptInDialog() {
-            activity?.let {
-                MaterialAlertDialogBuilder(it)
-                        .setTitle(R.string.threads_beta_enable_notice_title)
-                        .setMessage(threadsManager.getBetaEnableThreadsMessage())
-                        .setCancelable(true)
-                        .setNegativeButton(R.string.action_not_now) { _, _ -> }
-                        .setPositiveButton(R.string.action_try_it_out) { _, _ ->
-                            threadsManager.enableThreadsAndRestart(it)
-                        }
-                        .show()
-                        ?.findViewById(android.R.id.message)
-                        ?.apply {
-                            linksClickable = true
-                            movementMethod = LinkMovementMethod.getInstance()
-                        }
-            }
+        activity?.let {
+            MaterialAlertDialogBuilder(it)
+                    .setTitle(R.string.threads_beta_enable_notice_title)
+                    .setMessage(threadsManager.getBetaEnableThreadsMessage())
+                    .setCancelable(true)
+                    .setNegativeButton(R.string.action_not_now) { _, _ -> }
+                    .setPositiveButton(R.string.action_try_it_out) { _, _ ->
+                        threadsManager.enableThreadsAndRestart(it)
+                    }
+                    .show()
+                    ?.findViewById(android.R.id.message)
+                    ?.apply {
+                        linksClickable = true
+                        movementMethod = LinkMovementMethod.getInstance()
+                    }
         }
+    }
 
     /**
      * Navigate to Threads list for the current room
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
index 77284edba0a..b79b55b248e 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt
@@ -80,6 +80,7 @@ import org.matrix.android.sdk.api.session.crypto.MXCryptoError
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.LocalEcho
 import org.matrix.android.sdk.api.session.events.model.RelationType
+import org.matrix.android.sdk.api.session.events.model.content.WithHeldCode
 import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
 import org.matrix.android.sdk.api.session.events.model.isTextMessage
 import org.matrix.android.sdk.api.session.events.model.toContent
@@ -104,7 +105,6 @@ import org.matrix.android.sdk.api.session.widgets.model.WidgetType
 import org.matrix.android.sdk.api.util.toOptional
 import org.matrix.android.sdk.flow.flow
 import org.matrix.android.sdk.flow.unwrap
-import org.matrix.android.sdk.internal.crypto.model.event.WithHeldCode
 import timber.log.Timber
 import java.util.concurrent.atomic.AtomicBoolean
 
@@ -444,6 +444,7 @@ class TimelineViewModel @AssistedInject constructor(
                 _viewEvents.post(RoomDetailViewEvents.OpenRoom(action.replacementRoomId, closeCurrentRoom = true))
             }
             is RoomDetailAction.EndPoll                          -> handleEndPoll(action.eventId)
+            RoomDetailAction.StopLiveLocationSharing             -> handleStopLiveLocationSharing()
         }
     }
 
@@ -1093,6 +1094,10 @@ class TimelineViewModel @AssistedInject constructor(
                 }
     }
 
+    private fun handleStopLiveLocationSharing() {
+        locationSharingServiceConnection.stopLiveLocationSharing(room.roomId)
+    }
+
     private fun observeRoomSummary() {
         room.flow().liveRoomSummary()
                 .unwrap()
@@ -1111,9 +1116,13 @@ class TimelineViewModel @AssistedInject constructor(
             computeUnreadState(timelineEvents, roomSummary)
         }
                 // We don't want live update of unread so we skip when we already had a HasUnread or HasNoUnread
+                // However, we want to update an existing HasUnread, if the readMarkerId hasn't changed,
+                // as we might be loading new events to fill gaps in the timeline.
                 .distinctUntilChanged { previous, current ->
                     when {
                         previous is UnreadState.Unknown || previous is UnreadState.ReadMarkerNotLoaded -> false
+                        previous is UnreadState.HasUnread && current is UnreadState.HasUnread &&
+                                previous.readMarkerId == current.readMarkerId                          -> false
                         current is UnreadState.HasUnread || current is UnreadState.HasNoUnread         -> true
                         else                                                                           -> false
                     }
@@ -1132,12 +1141,17 @@ class TimelineViewModel @AssistedInject constructor(
                 } else {
                     UnreadState.Unknown
                 }
+        // If the read marker is at the bottom-most event, this doesn't mean we read all, in case we just haven't loaded more events.
+        // Avoid incorrectly returning HasNoUnread in this case.
+        if (firstDisplayableEventIndex == 0 && timeline.hasMoreToLoad(Timeline.Direction.FORWARDS)) {
+            return UnreadState.Unknown
+        }
         for (i in (firstDisplayableEventIndex - 1) downTo 0) {
             val timelineEvent = events.getOrNull(i) ?: return UnreadState.Unknown
             val eventId = timelineEvent.root.eventId ?: return UnreadState.Unknown
             val isFromMe = timelineEvent.root.senderId == session.myUserId
             if (!isFromMe) {
-                return UnreadState.HasUnread(eventId)
+                return UnreadState.HasUnread(eventId, readMarkerIdSnapshot)
             }
         }
         return UnreadState.HasNoUnread
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
similarity index 88%
rename from vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt
rename to vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
index c5d8b7a5c10..f4cab3305d2 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/VoiceMessageHelper.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/AudioMessageHelper.kt
@@ -21,7 +21,7 @@ import android.media.AudioAttributes
 import android.media.MediaPlayer
 import androidx.core.content.FileProvider
 import im.vector.app.BuildConfig
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.voice.VoiceFailure
 import im.vector.app.features.voice.VoiceRecorder
 import im.vector.app.features.voice.VoiceRecorderProvider
@@ -40,12 +40,13 @@ import javax.inject.Inject
 /**
  * Helper class to record audio for voice messages.
  */
-class VoiceMessageHelper @Inject constructor(
+class AudioMessageHelper @Inject constructor(
         private val context: Context,
-        private val playbackTracker: VoiceMessagePlaybackTracker,
+        private val playbackTracker: AudioMessagePlaybackTracker,
         voiceRecorderProvider: VoiceRecorderProvider
 ) {
     private var mediaPlayer: MediaPlayer? = null
+    private var currentPlayingId: String? = null
     private var voiceRecorder: VoiceRecorder = voiceRecorderProvider.provideVoiceRecorder()
 
     private val amplitudeList = mutableListOf()
@@ -58,7 +59,7 @@ class VoiceMessageHelper @Inject constructor(
         amplitudeList.clear()
         attachmentData.waveform?.let {
             amplitudeList.addAll(it)
-            playbackTracker.updateCurrentRecording(VoiceMessagePlaybackTracker.RECORDING_ID, amplitudeList)
+            playbackTracker.updateCurrentRecording(AudioMessagePlaybackTracker.RECORDING_ID, amplitudeList)
         }
     }
 
@@ -127,7 +128,7 @@ class VoiceMessageHelper @Inject constructor(
 
     fun startOrPauseRecordingPlayback() {
         voiceRecorder.getCurrentRecord()?.let {
-            startOrPausePlayback(VoiceMessagePlaybackTracker.RECORDING_ID, it)
+            startOrPausePlayback(AudioMessagePlaybackTracker.RECORDING_ID, it)
         }
     }
 
@@ -136,7 +137,8 @@ class VoiceMessageHelper @Inject constructor(
         mediaPlayer?.stop()
         stopPlaybackTicker()
         stopRecordingAmplitudes()
-        if (playbackState is VoiceMessagePlaybackTracker.Listener.State.Playing) {
+        currentPlayingId = null
+        if (playbackState is AudioMessagePlaybackTracker.Listener.State.Playing) {
             playbackTracker.pausePlayback(id)
         } else {
             startPlayback(id, file)
@@ -163,6 +165,7 @@ class VoiceMessageHelper @Inject constructor(
                     seekTo(currentPlaybackTime)
                 }
             }
+            currentPlayingId = id
         } catch (failure: Throwable) {
             Timber.e(failure, "Unable to start playback")
             throw VoiceFailure.UnableToPlay(failure)
@@ -171,17 +174,24 @@ class VoiceMessageHelper @Inject constructor(
     }
 
     fun stopPlayback() {
-        playbackTracker.pausePlayback(VoiceMessagePlaybackTracker.RECORDING_ID)
+        playbackTracker.pausePlayback(AudioMessagePlaybackTracker.RECORDING_ID)
         mediaPlayer?.stop()
         stopPlaybackTicker()
+        currentPlayingId = null
     }
 
     fun movePlaybackTo(id: String, percentage: Float, totalDuration: Int) {
         val toMillisecond = (totalDuration * percentage).toInt()
-        playbackTracker.updateCurrentPlaybackTime(id, toMillisecond, percentage)
+        playbackTracker.pauseAllPlaybacks()
 
-        stopPlayback()
-        playbackTracker.pausePlayback(id)
+        if (currentPlayingId == id) {
+            mediaPlayer?.seekTo(toMillisecond)
+            playbackTracker.updatePlayingAtPlaybackTime(id, toMillisecond, percentage)
+        } else {
+            mediaPlayer?.pause()
+            playbackTracker.updatePausedAtPlaybackTime(id, toMillisecond, percentage)
+            stopPlaybackTicker()
+        }
     }
 
     private fun startRecordingAmplitudes() {
@@ -200,7 +210,7 @@ class VoiceMessageHelper @Inject constructor(
         try {
             val maxAmplitude = voiceRecorder.getMaxAmplitude()
             amplitudeList.add(maxAmplitude)
-            playbackTracker.updateCurrentRecording(VoiceMessagePlaybackTracker.RECORDING_ID, amplitudeList)
+            playbackTracker.updateCurrentRecording(AudioMessagePlaybackTracker.RECORDING_ID, amplitudeList)
         } catch (e: IllegalStateException) {
             Timber.e(e, "Cannot get max amplitude. Amplitude recording timer will be stopped.")
             stopRecordingAmplitudes()
@@ -233,7 +243,7 @@ class VoiceMessageHelper @Inject constructor(
             val currentPosition = mediaPlayer?.currentPosition ?: 0
             val totalDuration = mediaPlayer?.duration ?: 0
             val percentage = currentPosition.toFloat() / totalDuration
-            playbackTracker.updateCurrentPlaybackTime(id, currentPosition, percentage)
+            playbackTracker.updatePlayingAtPlaybackTime(id, currentPosition, percentage)
         } else {
             playbackTracker.stopPlayback(id)
             stopPlaybackTicker()
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
index 091e9f7869c..0da324ffc20 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerAction.kt
@@ -17,6 +17,7 @@
 package im.vector.app.features.home.room.detail.composer
 
 import im.vector.app.core.platform.VectorViewModelAction
+import im.vector.app.features.command.ParsedCommand
 import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView
 import org.matrix.android.sdk.api.session.content.ContentAttachmentData
 import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
@@ -30,6 +31,7 @@ sealed class MessageComposerAction : VectorViewModelAction {
     data class UserIsTyping(val isTyping: Boolean) : MessageComposerAction()
     data class OnTextChanged(val text: CharSequence) : MessageComposerAction()
     data class OnEntersBackground(val composerText: String) : MessageComposerAction()
+    data class SlashCommandConfirmed(val parsedCommand: ParsedCommand) : MessageComposerAction()
 
     // Voice Message
     data class InitializeVoiceRecorder(val attachmentData: ContentAttachmentData) : MessageComposerAction()
@@ -42,4 +44,5 @@ sealed class MessageComposerAction : VectorViewModelAction {
     data class EndAllVoiceActions(val deleteRecord: Boolean = true) : MessageComposerAction()
     data class VoiceWaveformTouchedUp(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
     data class VoiceWaveformMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
+    data class AudioSeekBarMovedTo(val eventId: String, val duration: Int, val percentage: Float) : MessageComposerAction()
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewEvents.kt
index c1af838795b..e1f6923d214 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewEvents.kt
@@ -16,9 +16,9 @@
 
 package im.vector.app.features.home.room.detail.composer
 
-import androidx.annotation.StringRes
 import im.vector.app.core.platform.VectorViewEvents
 import im.vector.app.features.command.Command
+import im.vector.app.features.command.ParsedCommand
 
 sealed class MessageComposerViewEvents : VectorViewEvents {
 
@@ -30,13 +30,14 @@ sealed class MessageComposerViewEvents : VectorViewEvents {
 
     object MessageSent : SendMessageResult()
     data class JoinRoomCommandSuccess(val roomId: String) : SendMessageResult()
-    class SlashCommandError(val command: Command) : SendMessageResult()
-    class SlashCommandUnknown(val command: String) : SendMessageResult()
-    class SlashCommandNotSupportedInThreads(val command: Command) : SendMessageResult()
-    data class SlashCommandHandled(@StringRes val messageRes: Int? = null) : SendMessageResult()
+    data class SlashCommandError(val command: Command) : SendMessageResult()
+    data class SlashCommandUnknown(val command: String) : SendMessageResult()
+    data class SlashCommandNotSupportedInThreads(val command: Command) : SendMessageResult()
     object SlashCommandLoading : SendMessageResult()
-    data class SlashCommandResultOk(@StringRes val messageRes: Int? = null) : SendMessageResult()
-    class SlashCommandResultError(val throwable: Throwable) : SendMessageResult()
+    data class SlashCommandResultOk(val parsedCommand: ParsedCommand) : SendMessageResult()
+    data class SlashCommandResultError(val throwable: Throwable) : SendMessageResult()
+
+    data class SlashCommandConfirmationRequest(val parsedCommand: ParsedCommand) : MessageComposerViewEvents()
 
     data class OpenRoomMemberProfile(val userId: String) : MessageComposerViewEvents()
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
index 976489eec37..9c81a39941e 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/MessageComposerViewModel.kt
@@ -73,7 +73,7 @@ class MessageComposerViewModel @AssistedInject constructor(
         private val vectorPreferences: VectorPreferences,
         private val commandParser: CommandParser,
         private val rainbowGenerator: RainbowGenerator,
-        private val voiceMessageHelper: VoiceMessageHelper,
+        private val audioMessageHelper: AudioMessageHelper,
         private val analyticsTracker: AnalyticsTracker,
         private val voicePlayerHelper: VoicePlayerHelper
 ) : VectorViewModel(initialState) {
@@ -90,7 +90,6 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     override fun handle(action: MessageComposerAction) {
-        Timber.v("Handle action: $action")
         when (action) {
             is MessageComposerAction.EnterEditMode                  -> handleEnterEditMode(action)
             is MessageComposerAction.EnterQuoteMode                 -> handleEnterQuoteMode(action)
@@ -110,6 +109,8 @@ class MessageComposerViewModel @AssistedInject constructor(
             is MessageComposerAction.OnEntersBackground             -> handleEntersBackground(action.composerText)
             is MessageComposerAction.VoiceWaveformTouchedUp         -> handleVoiceWaveformTouchedUp(action)
             is MessageComposerAction.VoiceWaveformMovedTo           -> handleVoiceWaveformMovedTo(action)
+            is MessageComposerAction.AudioSeekBarMovedTo            -> handleAudioSeekBarMovedTo(action)
+            is MessageComposerAction.SlashCommandConfirmed          -> handleSlashCommandConfirmed(action)
         }
     }
 
@@ -195,7 +196,7 @@ class MessageComposerViewModel @AssistedInject constructor(
             }
             when (state.sendMode) {
                 is SendMode.Regular -> {
-                    when (val slashCommandResult = commandParser.parseSlashCommand(
+                    when (val parsedCommand = commandParser.parseSlashCommand(
                             textMessage = action.text,
                             isInThreadTimeline = state.isInThreadTimeline())) {
                         is ParsedCommand.ErrorNotACommand                  -> {
@@ -213,118 +214,117 @@ class MessageComposerViewModel @AssistedInject constructor(
                             popDraft()
                         }
                         is ParsedCommand.ErrorSyntax                       -> {
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandError(slashCommandResult.command))
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandError(parsedCommand.command))
                         }
                         is ParsedCommand.ErrorEmptySlashCommand            -> {
                             _viewEvents.post(MessageComposerViewEvents.SlashCommandUnknown("/"))
                         }
                         is ParsedCommand.ErrorUnknownSlashCommand          -> {
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandUnknown(slashCommandResult.slashCommand))
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandUnknown(parsedCommand.slashCommand))
                         }
                         is ParsedCommand.ErrorCommandNotSupportedInThreads -> {
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandNotSupportedInThreads(slashCommandResult.command))
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandNotSupportedInThreads(parsedCommand.command))
                         }
                         is ParsedCommand.SendPlainText                     -> {
                             // Send the text message to the room, without markdown
                             if (state.rootThreadEventId != null) {
                                 room.replyInThread(
                                         rootThreadEventId = state.rootThreadEventId,
-                                        replyInThreadText = slashCommandResult.message,
+                                        replyInThreadText = parsedCommand.message,
                                         autoMarkdown = false)
                             } else {
-                                room.sendTextMessage(slashCommandResult.message, autoMarkdown = false)
+                                room.sendTextMessage(parsedCommand.message, autoMarkdown = false)
                             }
                             _viewEvents.post(MessageComposerViewEvents.MessageSent)
                             popDraft()
                         }
                         is ParsedCommand.ChangeRoomName                    -> {
-                            handleChangeRoomNameSlashCommand(slashCommandResult)
+                            handleChangeRoomNameSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.Invite                            -> {
-                            handleInviteSlashCommand(slashCommandResult)
+                            handleInviteSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.Invite3Pid                        -> {
-                            handleInvite3pidSlashCommand(slashCommandResult)
+                            handleInvite3pidSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.SetUserPowerLevel                 -> {
-                            handleSetUserPowerLevel(slashCommandResult)
+                            handleSetUserPowerLevel(parsedCommand)
                         }
                         is ParsedCommand.ClearScalarToken                  -> {
                             // TODO
                             _viewEvents.post(MessageComposerViewEvents.SlashCommandNotImplemented)
                         }
                         is ParsedCommand.SetMarkdown                       -> {
-                            vectorPreferences.setMarkdownEnabled(slashCommandResult.enable)
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(
-                                    if (slashCommandResult.enable) R.string.markdown_has_been_enabled else R.string.markdown_has_been_disabled))
+                            vectorPreferences.setMarkdownEnabled(parsedCommand.enable)
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.BanUser                           -> {
-                            handleBanSlashCommand(slashCommandResult)
+                            handleBanSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.UnbanUser                         -> {
-                            handleUnbanSlashCommand(slashCommandResult)
+                            handleUnbanSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.IgnoreUser                        -> {
-                            handleIgnoreSlashCommand(slashCommandResult)
+                            handleIgnoreSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.UnignoreUser                      -> {
-                            handleUnignoreSlashCommand(slashCommandResult)
+                            handleUnignoreSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.RemoveUser                        -> {
-                            handleRemoveSlashCommand(slashCommandResult)
+                            handleRemoveSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.JoinRoom                          -> {
-                            handleJoinToAnotherRoomSlashCommand(slashCommandResult)
+                            handleJoinToAnotherRoomSlashCommand(parsedCommand)
                             popDraft()
                         }
                         is ParsedCommand.PartRoom                          -> {
-                            handlePartSlashCommand(slashCommandResult)
+                            handlePartSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.SendEmote                         -> {
                             if (state.rootThreadEventId != null) {
                                 room.replyInThread(
                                         rootThreadEventId = state.rootThreadEventId,
-                                        replyInThreadText = slashCommandResult.message,
+                                        replyInThreadText = parsedCommand.message,
                                         msgType = MessageType.MSGTYPE_EMOTE,
                                         autoMarkdown = action.autoMarkdown)
                             } else {
-                                room.sendTextMessage(slashCommandResult.message, msgType = MessageType.MSGTYPE_EMOTE, autoMarkdown = action.autoMarkdown)
+                                room.sendTextMessage(parsedCommand.message, msgType = MessageType.MSGTYPE_EMOTE, autoMarkdown = action.autoMarkdown)
                             }
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendRainbow                       -> {
-                            val message = slashCommandResult.message.toString()
+                            val message = parsedCommand.message.toString()
                             if (state.rootThreadEventId != null) {
                                 room.replyInThread(
                                         rootThreadEventId = state.rootThreadEventId,
-                                        replyInThreadText = slashCommandResult.message,
+                                        replyInThreadText = parsedCommand.message,
                                         formattedText = rainbowGenerator.generate(message))
                             } else {
                                 room.sendFormattedTextMessage(message, rainbowGenerator.generate(message))
                             }
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendRainbowEmote                  -> {
-                            val message = slashCommandResult.message.toString()
+                            val message = parsedCommand.message.toString()
                             if (state.rootThreadEventId != null) {
                                 room.replyInThread(
                                         rootThreadEventId = state.rootThreadEventId,
-                                        replyInThreadText = slashCommandResult.message,
+                                        replyInThreadText = parsedCommand.message,
                                         msgType = MessageType.MSGTYPE_EMOTE,
                                         formattedText = rainbowGenerator.generate(message))
                             } else {
                                 room.sendFormattedTextMessage(message, rainbowGenerator.generate(message), MessageType.MSGTYPE_EMOTE)
                             }
 
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendSpoiler                       -> {
-                            val text = "[${stringProvider.getString(R.string.spoiler)}](${slashCommandResult.message})"
-                            val formattedText = "${slashCommandResult.message}"
+                            val text = "[${stringProvider.getString(R.string.spoiler)}](${parsedCommand.message})"
+                            val formattedText = "${parsedCommand.message}"
                             if (state.rootThreadEventId != null) {
                                 room.replyInThread(
                                         rootThreadEventId = state.rootThreadEventId,
@@ -335,51 +335,51 @@ class MessageComposerViewModel @AssistedInject constructor(
                                         text,
                                         formattedText)
                             }
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendShrug                         -> {
-                            sendPrefixedMessage("¯\\_(ツ)_/¯", slashCommandResult.message, state.rootThreadEventId)
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            sendPrefixedMessage("¯\\_(ツ)_/¯", parsedCommand.message, state.rootThreadEventId)
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendLenny                         -> {
-                            sendPrefixedMessage("( ͡° ͜ʖ ͡°)", slashCommandResult.message, state.rootThreadEventId)
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            sendPrefixedMessage("( ͡° ͜ʖ ͡°)", parsedCommand.message, state.rootThreadEventId)
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.SendChatEffect                    -> {
-                            sendChatEffect(slashCommandResult)
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            sendChatEffect(parsedCommand)
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                         is ParsedCommand.ChangeTopic                       -> {
-                            handleChangeTopicSlashCommand(slashCommandResult)
+                            handleChangeTopicSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.ChangeDisplayName                 -> {
-                            handleChangeDisplayNameSlashCommand(slashCommandResult)
+                            handleChangeDisplayNameSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.ChangeDisplayNameForRoom          -> {
-                            handleChangeDisplayNameForRoomSlashCommand(slashCommandResult)
+                            handleChangeDisplayNameForRoomSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.ChangeRoomAvatar                  -> {
-                            handleChangeRoomAvatarSlashCommand(slashCommandResult)
+                            handleChangeRoomAvatarSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.ChangeAvatarForRoom               -> {
-                            handleChangeAvatarForRoomSlashCommand(slashCommandResult)
+                            handleChangeAvatarForRoomSlashCommand(parsedCommand)
                         }
                         is ParsedCommand.ShowUser                          -> {
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
-                            handleWhoisSlashCommand(slashCommandResult)
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
+                            handleWhoisSlashCommand(parsedCommand)
                             popDraft()
                         }
                         is ParsedCommand.DiscardSession                    -> {
                             if (room.isEncrypted()) {
                                 session.cryptoService().discardOutboundSession(room.roomId)
-                                _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 popDraft()
                             } else {
-                                _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 _viewEvents.post(
                                         MessageComposerViewEvents
                                                 .ShowMessage(stringProvider.getString(R.string.command_description_discard_session_not_handled))
@@ -391,8 +391,8 @@ class MessageComposerViewModel @AssistedInject constructor(
                             viewModelScope.launch(Dispatchers.IO) {
                                 try {
                                     val params = CreateSpaceParams().apply {
-                                        name = slashCommandResult.name
-                                        invitedUserIds.addAll(slashCommandResult.invitees)
+                                        name = parsedCommand.name
+                                        invitedUserIds.addAll(parsedCommand.invitees)
                                     }
                                     val spaceId = session.spaceService().createSpace(params)
                                     session.spaceService().getSpace(spaceId)
@@ -403,7 +403,7 @@ class MessageComposerViewModel @AssistedInject constructor(
                                                     true
                                             )
                                     popDraft()
-                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 } catch (failure: Throwable) {
                                     _viewEvents.post(MessageComposerViewEvents.SlashCommandResultError(failure))
                                 }
@@ -414,7 +414,7 @@ class MessageComposerViewModel @AssistedInject constructor(
                             _viewEvents.post(MessageComposerViewEvents.SlashCommandLoading)
                             viewModelScope.launch(Dispatchers.IO) {
                                 try {
-                                    session.spaceService().getSpace(slashCommandResult.spaceId)
+                                    session.spaceService().getSpace(parsedCommand.spaceId)
                                             ?.addChildren(
                                                     room.roomId,
                                                     null,
@@ -422,7 +422,7 @@ class MessageComposerViewModel @AssistedInject constructor(
                                                     false
                                             )
                                     popDraft()
-                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 } catch (failure: Throwable) {
                                     _viewEvents.post(MessageComposerViewEvents.SlashCommandResultError(failure))
                                 }
@@ -433,9 +433,9 @@ class MessageComposerViewModel @AssistedInject constructor(
                             _viewEvents.post(MessageComposerViewEvents.SlashCommandLoading)
                             viewModelScope.launch(Dispatchers.IO) {
                                 try {
-                                    session.spaceService().joinSpace(slashCommandResult.spaceIdOrAlias)
+                                    session.spaceService().joinSpace(parsedCommand.spaceIdOrAlias)
                                     popDraft()
-                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 } catch (failure: Throwable) {
                                     _viewEvents.post(MessageComposerViewEvents.SlashCommandResultError(failure))
                                 }
@@ -445,9 +445,9 @@ class MessageComposerViewModel @AssistedInject constructor(
                         is ParsedCommand.LeaveRoom                         -> {
                             viewModelScope.launch(Dispatchers.IO) {
                                 try {
-                                    session.leaveRoom(slashCommandResult.roomId)
+                                    session.leaveRoom(parsedCommand.roomId)
                                     popDraft()
-                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                                    _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                                 } catch (failure: Throwable) {
                                     _viewEvents.post(MessageComposerViewEvents.SlashCommandResultError(failure))
                                 }
@@ -457,11 +457,11 @@ class MessageComposerViewModel @AssistedInject constructor(
                         is ParsedCommand.UpgradeRoom                       -> {
                             _viewEvents.post(
                                     MessageComposerViewEvents.ShowRoomUpgradeDialog(
-                                            slashCommandResult.newVersion,
+                                            parsedCommand.newVersion,
                                             room.roomSummary()?.isPublic ?: false
                                     )
                             )
-                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk())
+                            _viewEvents.post(MessageComposerViewEvents.SlashCommandResultOk(parsedCommand))
                             popDraft()
                         }
                     }
@@ -644,19 +644,19 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handleChangeTopicSlashCommand(changeTopic: ParsedCommand.ChangeTopic) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeTopic) {
             room.updateTopic(changeTopic.topic)
         }
     }
 
     private fun handleInviteSlashCommand(invite: ParsedCommand.Invite) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(invite) {
             room.invite(invite.userId, invite.reason)
         }
     }
 
     private fun handleInvite3pidSlashCommand(invite: ParsedCommand.Invite3Pid) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(invite) {
             room.invite3pid(invite.threePid)
         }
     }
@@ -669,19 +669,19 @@ class MessageComposerViewModel @AssistedInject constructor(
                 ?.toContent()
                 ?: return
 
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(setUserPowerLevel) {
             room.sendStateEvent(EventType.STATE_ROOM_POWER_LEVELS, stateKey = "", newPowerLevelsContent)
         }
     }
 
     private fun handleChangeDisplayNameSlashCommand(changeDisplayName: ParsedCommand.ChangeDisplayName) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeDisplayName) {
             session.setDisplayName(session.myUserId, changeDisplayName.displayName)
         }
     }
 
     private fun handlePartSlashCommand(command: ParsedCommand.PartRoom) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(command) {
             if (command.roomAlias == null) {
                 // Leave the current room
                 room
@@ -697,25 +697,25 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handleRemoveSlashCommand(removeUser: ParsedCommand.RemoveUser) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(removeUser) {
             room.remove(removeUser.userId, removeUser.reason)
         }
     }
 
     private fun handleBanSlashCommand(ban: ParsedCommand.BanUser) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(ban) {
             room.ban(ban.userId, ban.reason)
         }
     }
 
     private fun handleUnbanSlashCommand(unban: ParsedCommand.UnbanUser) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(unban) {
             room.unban(unban.userId, unban.reason)
         }
     }
 
     private fun handleChangeRoomNameSlashCommand(changeRoomName: ParsedCommand.ChangeRoomName) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeRoomName) {
             room.updateName(changeRoomName.name)
         }
     }
@@ -727,7 +727,7 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handleChangeDisplayNameForRoomSlashCommand(changeDisplayName: ParsedCommand.ChangeDisplayNameForRoom) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeDisplayName) {
             getMyRoomMemberContent()
                     ?.copy(displayName = changeDisplayName.displayName)
                     ?.toContent()
@@ -738,13 +738,13 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handleChangeRoomAvatarSlashCommand(changeAvatar: ParsedCommand.ChangeRoomAvatar) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeAvatar) {
             room.sendStateEvent(EventType.STATE_ROOM_AVATAR, stateKey = "", RoomAvatarContent(changeAvatar.url).toContent())
         }
     }
 
     private fun handleChangeAvatarForRoomSlashCommand(changeAvatar: ParsedCommand.ChangeAvatarForRoom) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(changeAvatar) {
             getMyRoomMemberContent()
                     ?.copy(avatarUrl = changeAvatar.url)
                     ?.toContent()
@@ -755,13 +755,24 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handleIgnoreSlashCommand(ignore: ParsedCommand.IgnoreUser) {
-        launchSlashCommandFlowSuspendable {
+        launchSlashCommandFlowSuspendable(ignore) {
             session.ignoreUserIds(listOf(ignore.userId))
         }
     }
 
     private fun handleUnignoreSlashCommand(unignore: ParsedCommand.UnignoreUser) {
-        launchSlashCommandFlowSuspendable {
+        _viewEvents.post(MessageComposerViewEvents.SlashCommandConfirmationRequest(unignore))
+    }
+
+    private fun handleSlashCommandConfirmed(action: MessageComposerAction.SlashCommandConfirmed) {
+        when (action.parsedCommand) {
+            is ParsedCommand.UnignoreUser -> handleUnignoreSlashCommandConfirmed(action.parsedCommand)
+            else                          -> TODO("Not handled yet")
+        }
+    }
+
+    private fun handleUnignoreSlashCommandConfirmed(unignore: ParsedCommand.UnignoreUser) {
+        launchSlashCommandFlowSuspendable(unignore) {
             session.unIgnoreUserIds(listOf(unignore.userId))
         }
     }
@@ -811,18 +822,18 @@ class MessageComposerViewModel @AssistedInject constructor(
 
     private fun handleStartRecordingVoiceMessage() {
         try {
-            voiceMessageHelper.startRecording(room.roomId)
+            audioMessageHelper.startRecording(room.roomId)
         } catch (failure: Throwable) {
             _viewEvents.post(MessageComposerViewEvents.VoicePlaybackOrRecordingFailure(failure))
         }
     }
 
     private fun handleEndRecordingVoiceMessage(isCancelled: Boolean, rootThreadEventId: String? = null) {
-        voiceMessageHelper.stopPlayback()
+        audioMessageHelper.stopPlayback()
         if (isCancelled) {
-            voiceMessageHelper.deleteRecording()
+            audioMessageHelper.deleteRecording()
         } else {
-            voiceMessageHelper.stopRecording(convertForSending = true)?.let { audioType ->
+            audioMessageHelper.stopRecording(convertForSending = true)?.let { audioType ->
                 if (audioType.duration > 1000) {
                     room.sendMedia(
                             attachment = audioType.toContentAttachmentData(isVoiceMessage = true),
@@ -830,7 +841,7 @@ class MessageComposerViewModel @AssistedInject constructor(
                             roomIds = emptySet(),
                             rootThreadEventId = rootThreadEventId)
                 } else {
-                    voiceMessageHelper.deleteRecording()
+                    audioMessageHelper.deleteRecording()
                 }
             }
         }
@@ -845,7 +856,7 @@ class MessageComposerViewModel @AssistedInject constructor(
                 // Conversion can fail, fallback to the original file in this case and let the player fail for us
                 val convertedFile = voicePlayerHelper.convertFile(audioFile) ?: audioFile
                 // Play can fail
-                voiceMessageHelper.startOrPausePlayback(action.eventId, convertedFile)
+                audioMessageHelper.startOrPausePlayback(action.eventId, convertedFile)
             } catch (failure: Throwable) {
                 _viewEvents.post(MessageComposerViewEvents.VoicePlaybackOrRecordingFailure(failure))
             }
@@ -853,35 +864,38 @@ class MessageComposerViewModel @AssistedInject constructor(
     }
 
     private fun handlePlayOrPauseRecordingPlayback() {
-        voiceMessageHelper.startOrPauseRecordingPlayback()
+        audioMessageHelper.startOrPauseRecordingPlayback()
     }
 
     private fun handleEndAllVoiceActions(deleteRecord: Boolean) {
-        voiceMessageHelper.clearTracker()
-        voiceMessageHelper.stopAllVoiceActions(deleteRecord)
+        audioMessageHelper.clearTracker()
+        audioMessageHelper.stopAllVoiceActions(deleteRecord)
     }
 
     private fun handleInitializeVoiceRecorder(attachmentData: ContentAttachmentData) {
-        voiceMessageHelper.initializeRecorder(attachmentData)
+        audioMessageHelper.initializeRecorder(attachmentData)
         setState { copy(voiceRecordingUiState = VoiceMessageRecorderView.RecordingUiState.Draft) }
     }
 
     private fun handlePauseRecordingVoiceMessage() {
-        voiceMessageHelper.pauseRecording()
+        audioMessageHelper.pauseRecording()
     }
 
     private fun handleVoiceWaveformTouchedUp(action: MessageComposerAction.VoiceWaveformTouchedUp) {
-        voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
+        audioMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
     }
 
     private fun handleVoiceWaveformMovedTo(action: MessageComposerAction.VoiceWaveformMovedTo) {
-        voiceMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
+        audioMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
+    }
+
+    private fun handleAudioSeekBarMovedTo(action: MessageComposerAction.AudioSeekBarMovedTo) {
+        audioMessageHelper.movePlaybackTo(action.eventId, action.percentage, action.duration)
     }
 
     private fun handleEntersBackground(composerText: String) {
         // Always stop all voice actions. It may be playing in timeline or active recording
-        val playingAudioContent = voiceMessageHelper.stopAllVoiceActions(deleteRecord = false)
-        voiceMessageHelper.clearTracker()
+        val playingAudioContent = audioMessageHelper.stopAllVoiceActions(deleteRecord = false)
 
         val isVoiceRecording = com.airbnb.mvrx.withState(this) { it.isVoiceRecording }
         if (isVoiceRecording) {
@@ -897,13 +911,13 @@ class MessageComposerViewModel @AssistedInject constructor(
         }
     }
 
-    private fun launchSlashCommandFlowSuspendable(block: suspend () -> Unit) {
+    private fun launchSlashCommandFlowSuspendable(parsedCommand: ParsedCommand, block: suspend () -> Unit) {
         _viewEvents.post(MessageComposerViewEvents.SlashCommandLoading)
         viewModelScope.launch {
             val event = try {
                 block()
                 popDraft()
-                MessageComposerViewEvents.SlashCommandResultOk()
+                MessageComposerViewEvents.SlashCommandResultOk(parsedCommand)
             } catch (failure: Throwable) {
                 MessageComposerViewEvents.SlashCommandResultError(failure)
             }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
index ab37d1a48c4..b898aaf114d 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageRecorderView.kt
@@ -27,7 +27,7 @@ import im.vector.app.core.hardware.vibrate
 import im.vector.app.core.time.Clock
 import im.vector.app.core.utils.DimensionConverter
 import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.lib.core.utils.timer.CountUpTimer
 import javax.inject.Inject
 import kotlin.math.floor
@@ -40,7 +40,7 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         context: Context,
         attrs: AttributeSet? = null,
         defStyleAttr: Int = 0
-) : ConstraintLayout(context, attrs, defStyleAttr), VoiceMessagePlaybackTracker.Listener {
+) : ConstraintLayout(context, attrs, defStyleAttr), AudioMessagePlaybackTracker.Listener {
 
     interface Callback {
         fun onVoiceRecordingStarted()
@@ -222,16 +222,16 @@ class VoiceMessageRecorderView @JvmOverloads constructor(
         recordingTicker = null
     }
 
-    override fun onUpdate(state: VoiceMessagePlaybackTracker.Listener.State) {
+    override fun onUpdate(state: AudioMessagePlaybackTracker.Listener.State) {
         when (state) {
-            is VoiceMessagePlaybackTracker.Listener.State.Recording -> {
+            is AudioMessagePlaybackTracker.Listener.State.Recording -> {
                 voiceMessageViews.renderRecordingWaveform(state.amplitudeList.toTypedArray())
             }
-            is VoiceMessagePlaybackTracker.Listener.State.Playing   -> {
+            is AudioMessagePlaybackTracker.Listener.State.Playing   -> {
                 voiceMessageViews.renderPlaying(state)
             }
-            is VoiceMessagePlaybackTracker.Listener.State.Paused,
-            is VoiceMessagePlaybackTracker.Listener.State.Idle      -> {
+            is AudioMessagePlaybackTracker.Listener.State.Paused,
+            is AudioMessagePlaybackTracker.Listener.State.Idle      -> {
                 voiceMessageViews.renderIdle()
             }
         }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
index 7a76657923d..0256064af2f 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/voice/VoiceMessageViews.kt
@@ -35,7 +35,7 @@ import im.vector.app.core.utils.DimensionConverter
 import im.vector.app.databinding.ViewVoiceMessageRecorderBinding
 import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.DraggingState
 import im.vector.app.features.home.room.detail.composer.voice.VoiceMessageRecorderView.RecordingUiState
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.themes.ThemeUtils
 import im.vector.app.features.voice.AudioWaveformView
 
@@ -303,7 +303,7 @@ class VoiceMessageViews(
         views.voicePlaybackWaveform.post { views.voicePlaybackWaveform.clear() }
     }
 
-    fun renderPlaying(state: VoiceMessagePlaybackTracker.Listener.State.Playing) {
+    fun renderPlaying(state: AudioMessagePlaybackTracker.Listener.State.Playing) {
         views.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
         views.voicePlaybackControlButton.contentDescription = resources.getString(R.string.a11y_pause_voice_message)
         val formattedTimerText = DateUtils.formatElapsedTime((state.playbackTime / 1000).toLong())
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
index 023c28cdc72..981e5740d75 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/TimelineEventController.kt
@@ -148,6 +148,8 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
         fun onVoiceWaveformTouchedUp(eventId: String, duration: Int, percentage: Float)
         fun onVoiceWaveformMovedTo(eventId: String, duration: Int, percentage: Float)
 
+        fun onAudioSeekBarMovedTo(eventId: String, duration: Int, percentage: Float)
+
         fun onAddMoreReaction(event: TimelineEvent)
     }
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/LocationUiData.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/LocationUiData.kt
new file mode 100644
index 00000000000..c50c6492216
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/LocationUiData.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home.room.detail.timeline.action
+
+import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
+
+/**
+ * Data used to display Location data in the message bottom sheet
+ */
+data class LocationUiData(
+        val locationUrl: String,
+        val locationOwnerId: String?,
+        val locationPinProvider: LocationPinProvider,
+)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
index 307be220d3d..41916c609da 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsEpoxyController.kt
@@ -46,8 +46,8 @@ import im.vector.app.features.media.ImageContentRenderer
 import im.vector.app.features.settings.VectorPreferences
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
 import org.matrix.android.sdk.api.extensions.orFalse
-import org.matrix.android.sdk.api.extensions.orTrue
 import org.matrix.android.sdk.api.failure.Failure
+import org.matrix.android.sdk.api.session.events.model.isLocationMessage
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
 import org.matrix.android.sdk.api.session.room.send.SendState
@@ -80,12 +80,7 @@ class MessageActionsEpoxyController @Inject constructor(
         val formattedDate = dateFormatter.format(date, DateFormatKind.MESSAGE_DETAIL)
         val body = state.messageBody.linkify(host.listener)
         val bindingOptions = spanUtils.getBindingOptions(body)
-
-        val locationContent = state.timelineEvent()?.root?.getClearContent()
-                ?.toModel(catchError = true)
-        val locationUrl = locationContent?.toLocationData()
-                ?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) }
-        val locationOwnerId = if (locationContent?.isSelfLocation().orTrue()) state.informationData.matrixItem.id else null
+        val locationUiData = buildLocationUiData(state)
 
         bottomSheetMessagePreviewItem {
             id("preview")
@@ -99,9 +94,7 @@ class MessageActionsEpoxyController @Inject constructor(
             body(body.toEpoxyCharSequence())
             bodyDetails(host.eventDetailsFormatter.format(state.timelineEvent()?.root)?.toEpoxyCharSequence())
             time(formattedDate)
-            locationUrl(locationUrl)
-            locationPinProvider(host.locationPinProvider)
-            locationOwnerId(locationOwnerId)
+            locationUiData(locationUiData)
         }
 
         // Send state
@@ -222,6 +215,23 @@ class MessageActionsEpoxyController @Inject constructor(
         }
     }
 
+    private fun buildLocationUiData(state: MessageActionState): LocationUiData? {
+        if (state.timelineEvent()?.root?.isLocationMessage() != true) return null
+
+        val locationContent = state.timelineEvent()?.root?.getClearContent().toModel(catchError = true)
+                ?: return null
+        val locationUrl = locationContent.toLocationData()
+                ?.let { urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, 1200, 800) }
+                ?: return null
+        val locationOwnerId = if (locationContent.isSelfLocation()) state.informationData.matrixItem.id else null
+
+        return LocationUiData(
+                locationUrl = locationUrl,
+                locationOwnerId = locationOwnerId,
+                locationPinProvider = locationPinProvider,
+        )
+    }
+
     private fun EventSharedAction.shouldShowBetaLabel(): Boolean =
             this is EventSharedAction.ReplyInThread && !vectorPreferences.areThreadMessagesEnabled()
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
index 9a73afd897f..99c36d11900 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt
@@ -452,6 +452,10 @@ class MessageActionsViewModel @AssistedInject constructor(
                                  actionPermissions: ActionPermissions): Boolean {
         // We let reply in thread visible even if threads are not enabled, with an enhanced flow to attract users
 //        if (!vectorPreferences.areThreadMessagesEnabled()) return false
+        // Disable beta prompt if the homeserver do not support threads
+        if (!vectorPreferences.areThreadMessagesEnabled() &&
+                !session.getHomeServerCapabilities().canUseThreading) return false
+
         if (initialState.isFromThreadTimeline) return false
         if (event.root.isThread()) return false
         if (event.root.getClearType() != EventType.MESSAGE &&
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
index 9f055473002..63a34fe7132 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryEpoxyController.kt
@@ -38,7 +38,7 @@ import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
 import org.matrix.android.sdk.api.util.ContentUtils.extractUsefulTextFromReply
-import org.matrix.android.sdk.internal.session.room.send.TextContent
+import org.matrix.android.sdk.api.util.TextContent
 import java.util.Calendar
 import javax.inject.Inject
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt
index 9abc67e41f9..e1d4d71c6a2 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/edithistory/ViewEditHistoryViewModel.kt
@@ -30,8 +30,8 @@ import im.vector.app.core.platform.VectorViewModel
 import kotlinx.coroutines.launch
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
+import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult
 import org.matrix.android.sdk.api.session.events.model.isReply
-import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult
 import timber.log.Timber
 import java.util.UUID
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
index 2b04600af2f..dd91f00ab9b 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptedItemFactory.kt
@@ -32,8 +32,8 @@ import me.gujun.android.span.image
 import me.gujun.android.span.span
 import org.matrix.android.sdk.api.session.crypto.MXCryptoError
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
 import javax.inject.Inject
 
 // This class handles timeline events who haven't been successfully decrypted
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
index 0cb86a5c1cd..89899a52e03 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/EncryptionItemFactory.kt
@@ -24,11 +24,11 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio
 import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
 import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem
 import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem_
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
 import javax.inject.Inject
 
 class EncryptionItemFactory @Inject constructor(
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationMessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationMessageItemFactory.kt
new file mode 100644
index 00000000000..9bc148a562e
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/LiveLocationMessageItemFactory.kt
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home.room.detail.timeline.factory
+
+import im.vector.app.core.epoxy.VectorEpoxyModel
+import im.vector.app.core.utils.DimensionConverter
+import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
+import im.vector.app.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
+import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
+import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocationStartItem
+import im.vector.app.features.home.room.detail.timeline.item.MessageLiveLocationStartItem_
+import org.matrix.android.sdk.api.extensions.orFalse
+import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent
+import javax.inject.Inject
+
+class LiveLocationMessageItemFactory @Inject constructor(
+        private val dimensionConverter: DimensionConverter,
+        private val timelineMediaSizeProvider: TimelineMediaSizeProvider,
+        private val avatarSizeProvider: AvatarSizeProvider,
+) {
+
+    fun create(
+            liveLocationContent: LiveLocationBeaconContent,
+            highlight: Boolean,
+            attributes: AbsMessageItem.Attributes,
+    ): VectorEpoxyModel<*>? {
+        // TODO handle location received and stopped states
+        return when {
+            isLiveRunning(liveLocationContent) -> buildStartLiveItem(highlight, attributes)
+            else                               -> null
+        }
+    }
+
+    private fun isLiveRunning(liveLocationContent: LiveLocationBeaconContent): Boolean {
+        return liveLocationContent.getBestBeaconInfo()?.isLive.orFalse() && liveLocationContent.hasTimedOut.not()
+    }
+
+    private fun buildStartLiveItem(
+            highlight: Boolean,
+            attributes: AbsMessageItem.Attributes,
+    ): MessageLiveLocationStartItem {
+        val width = timelineMediaSizeProvider.getMaxSize().first
+        val height = dimensionConverter.dpToPx(MessageItemFactory.MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
+
+        return MessageLiveLocationStartItem_()
+                .attributes(attributes)
+                .mapWidth(width)
+                .mapHeight(height)
+                .highlighted(highlight)
+                .leftGuideline(avatarSizeProvider.leftGuideline)
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt
index 76ed024370d..c21b67a4596 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MergedHeaderItemFactory.kt
@@ -32,16 +32,16 @@ import im.vector.app.features.home.room.detail.timeline.item.MergedRoomCreationI
 import im.vector.app.features.home.room.detail.timeline.item.MergedSimilarEventsItem
 import im.vector.app.features.home.room.detail.timeline.item.MergedSimilarEventsItem_
 import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.query.QueryStringValue
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.PowerLevelsContent
 import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
 import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
 import javax.inject.Inject
 
 class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolder: ActiveSessionHolder,
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
index 03fda1ee6cb..1787da2ae70 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt
@@ -34,6 +34,7 @@ import im.vector.app.core.resources.StringProvider
 import im.vector.app.core.utils.DimensionConverter
 import im.vector.app.core.utils.containsOnlyEmojis
 import im.vector.app.features.home.room.detail.timeline.TimelineEventController
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvider
 import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
 import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
@@ -41,8 +42,9 @@ import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvid
 import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory
 import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
 import im.vector.app.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
+import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem
+import im.vector.app.features.home.room.detail.timeline.item.MessageAudioItem_
 import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem
 import im.vector.app.features.home.room.detail.timeline.item.MessageFileItem_
 import im.vector.app.features.home.room.detail.timeline.item.MessageImageVideoItem
@@ -91,9 +93,12 @@ import me.gujun.android.span.span
 import org.matrix.android.sdk.api.MatrixUrls.isMxcUrl
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt
 import org.matrix.android.sdk.api.session.events.model.RelationType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.isThread
 import org.matrix.android.sdk.api.session.events.model.toModel
+import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageContent
 import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
@@ -109,14 +114,11 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVerification
 import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
 import org.matrix.android.sdk.api.session.room.model.message.PollAnswer
 import org.matrix.android.sdk.api.session.room.model.message.PollType
-import org.matrix.android.sdk.api.session.room.model.message.getFileName
 import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
 import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
 import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import org.matrix.android.sdk.api.util.MimeTypes
-import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
 import javax.inject.Inject
 
 class MessageItemFactory @Inject constructor(
@@ -140,10 +142,11 @@ class MessageItemFactory @Inject constructor(
     private val lightweightSettingsStorage: LightweightSettingsStorage,
     private val spanUtils: SpanUtils,
     private val session: Session,
-    private val voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker,
+    private val audioMessagePlaybackTracker: AudioMessagePlaybackTracker,
     private val locationPinProvider: LocationPinProvider,
     private val vectorPreferences: VectorPreferences,
     private val urlMapProvider: UrlMapProvider,
+    private val liveLocationMessageItemFactory: LiveLocationMessageItemFactory,
 ) {
 
     // TODO inject this properly?
@@ -201,13 +204,7 @@ class MessageItemFactory @Inject constructor(
             is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, highlight, callback, attributes)
             is MessageVideoContent -> buildVideoMessageItem(messageContent, informationData, highlight, callback, attributes)
             is MessageFileContent -> buildFileMessageItem(messageContent, highlight, attributes)
-            is MessageAudioContent -> {
-                if (messageContent.voiceMessageIndicator != null) {
-                    buildVoiceMessageItem(params, messageContent, informationData, highlight, attributes)
-                } else {
-                    buildAudioMessageItem(messageContent, informationData, highlight, attributes)
-                }
-            }
+            is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, attributes)
             is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
             is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
             is MessageLocationContent -> {
@@ -217,6 +214,7 @@ class MessageItemFactory @Inject constructor(
                     buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
                 }
             }
+            is LiveLocationBeaconContent -> liveLocationMessageItemFactory.create(messageContent, highlight, attributes)
             else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
         }
         return messageItem?.apply {
@@ -231,7 +229,7 @@ class MessageItemFactory @Inject constructor(
         attributes: AbsMessageItem.Attributes,
     ): MessageLocationItem? {
         val width = timelineMediaSizeProvider.getMaxSize().first
-        val height = dimensionConverter.dpToPx(200)
+        val height = dimensionConverter.dpToPx(MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP)
 
         val locationUrl = locationContent.toLocationData()?.let {
             urlMapProvider.buildStaticMapUrl(it, INITIAL_MAP_ZOOM_IN_TIMELINE, width, height)
@@ -279,9 +277,9 @@ class MessageItemFactory @Inject constructor(
     }
 
     private fun createPollState(
-        informationData: MessageInformationData,
-        pollResponseSummary: PollResponseData?,
-        pollContent: MessagePollContent,
+            informationData: MessageInformationData,
+            pollResponseSummary: PollResponseData?,
+            pollContent: MessagePollContent,
     ): PollState = when {
         !informationData.sendState.isSent() -> Sending
         pollResponseSummary?.isClosed.orFalse() -> Ended
@@ -291,8 +289,8 @@ class MessageItemFactory @Inject constructor(
     }
 
     private fun List.mapToOptions(
-        pollState: PollState,
-        informationData: MessageInformationData,
+            pollState: PollState,
+            informationData: MessageInformationData,
     ) = map { answer ->
         val pollResponseSummary = informationData.pollResponseAggregatedSummary
         val winnerVoteCount = pollResponseSummary?.winnerVoteCount
@@ -314,9 +312,9 @@ class MessageItemFactory @Inject constructor(
     }
 
     private fun createPollQuestion(
-        informationData: MessageInformationData,
-        question: String,
-        callback: TimelineEventController.Callback?,
+            informationData: MessageInformationData,
+            question: String,
+            callback: TimelineEventController.Callback?,
     ) = if (informationData.hasBeenEdited) {
         annotateWithEdited(question, callback, informationData)
     } else {
@@ -324,8 +322,8 @@ class MessageItemFactory @Inject constructor(
     }.toEpoxyCharSequence()
 
     private fun createTotalVotesText(
-        pollState: PollState,
-        pollResponseSummary: PollResponseData?,
+            pollState: PollState,
+            pollResponseSummary: PollResponseData?,
     ): String {
         val votes = pollResponseSummary?.totalVotes ?: 0
         return when {
@@ -338,58 +336,62 @@ class MessageItemFactory @Inject constructor(
     }
 
     private fun buildAudioMessageItem(
-        messageContent: MessageAudioContent,
-        @Suppress("UNUSED_PARAMETER")
-        informationData: MessageInformationData,
-        highlight: Boolean,
-        attributes: AbsMessageItem.Attributes,
-    ): MessageFileItem? {
-        val fileUrl = messageContent.getFileUrl()?.let {
-            if (informationData.sentByMe && !informationData.sendState.isSent()) {
-                it
-            } else {
-                it.takeIf { it.isMxcUrl() }
-            }
-        } ?: ""
-        return MessageFileItem_()
-            .attributes(attributes)
-            .izLocalFile(localFilesHelper.isLocalFile(fileUrl))
-            .izDownloaded(session.fileService().isFileInCache(
-                fileUrl,
-                messageContent.getFileName(),
-                messageContent.mimeType,
-                messageContent.encryptedFileInfo?.toElementToDecrypt())
-            )
-            .mxcUrl(fileUrl)
-            .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
-            .contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
-            .highlighted(highlight)
-            .leftGuideline(avatarSizeProvider.leftGuideline)
-            .filename(messageContent.body)
-            .iconRes(R.drawable.ic_headphones)
+            params: TimelineItemFactoryParams,
+            messageContent: MessageAudioContent,
+            informationData: MessageInformationData,
+            highlight: Boolean,
+            attributes: AbsMessageItem.Attributes
+    ): MessageAudioItem {
+        val fileUrl = getAudioFileUrl(messageContent, informationData)
+        val playbackControlButtonClickListener = createOnPlaybackButtonClickListener(messageContent, informationData, params)
+        val duration = messageContent.audioInfo?.duration ?: 0
+
+        return MessageAudioItem_()
+                .attributes(attributes)
+                .filename(messageContent.body)
+                .duration(messageContent.audioInfo?.duration ?: 0)
+                .playbackControlButtonClickListener(playbackControlButtonClickListener)
+                .audioMessagePlaybackTracker(audioMessagePlaybackTracker)
+                .isLocalFile(localFilesHelper.isLocalFile(fileUrl))
+                .fileSize(messageContent.audioInfo?.size ?: 0L)
+                .onSeek { params.callback?.onAudioSeekBarMovedTo(informationData.eventId, duration, it) }
+                .mxcUrl(fileUrl)
+                .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
+                .contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
+                .highlighted(highlight)
+                .leftGuideline(avatarSizeProvider.leftGuideline)
     }
 
-    private fun buildVoiceMessageItem(
-        params: TimelineItemFactoryParams,
-        messageContent: MessageAudioContent,
-        @Suppress("UNUSED_PARAMETER")
-        informationData: MessageInformationData,
-        highlight: Boolean,
-        attributes: AbsMessageItem.Attributes,
-    ): MessageVoiceItem? {
-        val fileUrl = messageContent.getFileUrl()?.let {
-            if (informationData.sentByMe && !informationData.sendState.isSent()) {
-                it
-            } else {
-                it.takeIf { it.isMxcUrl() }
-            }
-        } ?: ""
-
-        val playbackControlButtonClickListener: ClickListener = object : ClickListener {
-            override fun invoke(view: View) {
-                params.callback?.onVoiceControlButtonClicked(informationData.eventId, messageContent)
-            }
+    private fun getAudioFileUrl(
+            messageContent: MessageAudioContent,
+            informationData: MessageInformationData,
+    ) = messageContent.getFileUrl()?.let {
+        if (informationData.sentByMe && !informationData.sendState.isSent()) {
+            it
+        } else {
+            it.takeIf { it.isMxcUrl() }
+        }
+    } ?: ""
+
+    private fun createOnPlaybackButtonClickListener(
+            messageContent: MessageAudioContent,
+            informationData: MessageInformationData,
+            params: TimelineItemFactoryParams,
+    ) = object : ClickListener {
+        override fun invoke(view: View) {
+            params.callback?.onVoiceControlButtonClicked(informationData.eventId, messageContent)
         }
+    }
+
+    private fun buildVoiceMessageItem(
+            params: TimelineItemFactoryParams,
+            messageContent: MessageAudioContent,
+            informationData: MessageInformationData,
+            highlight: Boolean,
+            attributes: AbsMessageItem.Attributes
+    ): MessageVoiceItem {
+        val fileUrl = getAudioFileUrl(messageContent, informationData)
+        val playbackControlButtonClickListener = createOnPlaybackButtonClickListener(messageContent, informationData, params)
 
         val waveformTouchListener: MessageVoiceItem.WaveformTouchListener = object : MessageVoiceItem.WaveformTouchListener {
             override fun onWaveformTouchedUp(percentage: Float) {
@@ -409,14 +411,8 @@ class MessageItemFactory @Inject constructor(
             .waveform(messageContent.audioWaveformInfo?.waveform?.toFft().orEmpty())
             .playbackControlButtonClickListener(playbackControlButtonClickListener)
             .waveformTouchListener(waveformTouchListener)
-            .voiceMessagePlaybackTracker(voiceMessagePlaybackTracker)
-            .izLocalFile(localFilesHelper.isLocalFile(fileUrl))
-            .izDownloaded(session.fileService().isFileInCache(
-                fileUrl,
-                messageContent.getFileName(),
-                messageContent.mimeType,
-                messageContent.encryptedFileInfo?.toElementToDecrypt())
-            )
+            .audioMessagePlaybackTracker(audioMessagePlaybackTracker)
+            .isLocalFile(localFilesHelper.isLocalFile(fileUrl))
             .mxcUrl(fileUrl)
             .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
             .contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
@@ -470,13 +466,13 @@ class MessageItemFactory @Inject constructor(
         messageContent: MessageFileContent,
         highlight: Boolean,
         attributes: AbsMessageItem.Attributes,
-    ): MessageFileItem? {
+    ): MessageFileItem {
         val mxcUrl = messageContent.getFileUrl() ?: ""
         return MessageFileItem_()
             .attributes(attributes)
             .leftGuideline(avatarSizeProvider.leftGuideline)
-            .izLocalFile(localFilesHelper.isLocalFile(messageContent.getFileUrl()))
-            .izDownloaded(session.fileService().isFileInCache(messageContent))
+            .isLocalFile(localFilesHelper.isLocalFile(messageContent.getFileUrl()))
+            .isDownloaded(session.fileService().isFileInCache(messageContent))
             .mxcUrl(mxcUrl)
             .contentUploadStateTrackerBinder(contentUploadStateTrackerBinder)
             .contentDownloadStateTrackerBinder(contentDownloadStateTrackerBinder)
@@ -485,13 +481,24 @@ class MessageItemFactory @Inject constructor(
             .iconRes(R.drawable.ic_paperclip)
     }
 
+    private fun buildAudioContent(
+            params: TimelineItemFactoryParams,
+            messageContent: MessageAudioContent,
+            informationData: MessageInformationData,
+            highlight: Boolean,
+            attributes: AbsMessageItem.Attributes,
+    ) = if (messageContent.voiceMessageIndicator != null) {
+                buildVoiceMessageItem(params, messageContent, informationData, highlight, attributes)
+            } else {
+                buildAudioMessageItem(params, messageContent, informationData, highlight, attributes)
+            }
+
     private fun buildNotHandledMessageItem(
-        messageContent: MessageContent,
-        informationData: MessageInformationData,
-        highlight: Boolean,
-        callback: TimelineEventController.Callback?,
-        attributes: AbsMessageItem.Attributes,
-    ): MessageTextItem? {
+            messageContent: MessageContent,
+            informationData: MessageInformationData,
+            highlight: Boolean,
+            callback: TimelineEventController.Callback?,
+            attributes: AbsMessageItem.Attributes): MessageTextItem? {
         // For compatibility reason we should display the body
         return buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
     }
@@ -770,5 +777,6 @@ class MessageItemFactory @Inject constructor(
 
     companion object {
         private const val MAX_NUMBER_OF_EMOJI_FOR_BIG_FONT = 5
+        const val MESSAGE_LOCATION_ITEM_HEIGHT_IN_DP = 200
     }
 }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/TimelineItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
index f9d2613e276..b5d620658e6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/TimelineItemFactory.kt
@@ -26,17 +26,19 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import timber.log.Timber
 import javax.inject.Inject
 
-class TimelineItemFactory @Inject constructor(private val messageItemFactory: MessageItemFactory,
-                                              private val encryptedItemFactory: EncryptedItemFactory,
-                                              private val noticeItemFactory: NoticeItemFactory,
-                                              private val defaultItemFactory: DefaultItemFactory,
-                                              private val encryptionItemFactory: EncryptionItemFactory,
-                                              private val roomCreateItemFactory: RoomCreateItemFactory,
-                                              private val widgetItemFactory: WidgetItemFactory,
-                                              private val verificationConclusionItemFactory: VerificationItemFactory,
-                                              private val callItemFactory: CallItemFactory,
-                                              private val decryptionFailureTracker: DecryptionFailureTracker,
-                                              private val timelineEventVisibilityHelper: TimelineEventVisibilityHelper) {
+class TimelineItemFactory @Inject constructor(
+        private val messageItemFactory: MessageItemFactory,
+        private val encryptedItemFactory: EncryptedItemFactory,
+        private val noticeItemFactory: NoticeItemFactory,
+        private val defaultItemFactory: DefaultItemFactory,
+        private val encryptionItemFactory: EncryptionItemFactory,
+        private val roomCreateItemFactory: RoomCreateItemFactory,
+        private val widgetItemFactory: WidgetItemFactory,
+        private val verificationConclusionItemFactory: VerificationItemFactory,
+        private val callItemFactory: CallItemFactory,
+        private val decryptionFailureTracker: DecryptionFailureTracker,
+        private val timelineEventVisibilityHelper: TimelineEventVisibilityHelper,
+) {
 
     /**
      * Reminder: nextEvent is older and prevEvent is newer.
@@ -75,16 +77,17 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
                     EventType.STATE_ROOM_ALIASES,
                     EventType.STATE_SPACE_CHILD,
                     EventType.STATE_SPACE_PARENT,
-                    EventType.STATE_ROOM_POWER_LEVELS -> {
+                    EventType.STATE_ROOM_POWER_LEVELS   -> {
                         noticeItemFactory.create(params)
                     }
                     EventType.STATE_ROOM_WIDGET_LEGACY,
-                    EventType.STATE_ROOM_WIDGET       -> widgetItemFactory.create(params)
-                    EventType.STATE_ROOM_ENCRYPTION   -> encryptionItemFactory.create(params)
+                    EventType.STATE_ROOM_WIDGET         -> widgetItemFactory.create(params)
+                    EventType.STATE_ROOM_ENCRYPTION     -> encryptionItemFactory.create(params)
                     // State room create
-                    EventType.STATE_ROOM_CREATE       -> roomCreateItemFactory.create(params)
+                    EventType.STATE_ROOM_CREATE         -> roomCreateItemFactory.create(params)
+                    in EventType.STATE_ROOM_BEACON_INFO -> messageItemFactory.create(params)
                     // Unhandled state event types
-                    else                              -> {
+                    else                                -> {
                         // Should only happen when shouldShowHiddenEvents() settings is ON
                         Timber.v("State event type ${event.root.type} not handled")
                         defaultItemFactory.create(params)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt
index 16cf73cbb00..fb8f8fce9db 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/VerificationItemFactory.kt
@@ -25,9 +25,9 @@ import im.vector.app.features.home.room.detail.timeline.helper.MessageInformatio
 import im.vector.app.features.home.room.detail.timeline.helper.MessageItemAttributesFactory
 import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem
 import im.vector.app.features.home.room.detail.timeline.item.StatusTileTimelineItem_
-import org.matrix.android.sdk.api.crypto.VerificationState
 import org.matrix.android.sdk.api.session.Session
 import org.matrix.android.sdk.api.session.crypto.verification.CancelCode
+import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
 import org.matrix.android.sdk.api.session.crypto.verification.safeValueOf
 import org.matrix.android.sdk.api.session.events.model.EventType
 import org.matrix.android.sdk.api.session.events.model.RelationType
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
index b83322dc9b7..3c2bdb53ab6 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/DisplayableEventFormatter.kt
@@ -59,7 +59,7 @@ class DisplayableEventFormatter @Inject constructor(
         val senderName = timelineEvent.senderInfo.disambiguatedDisplayName
 
         return when (timelineEvent.root.getClearType()) {
-            EventType.MESSAGE               -> {
+            EventType.MESSAGE                   -> {
                 timelineEvent.getLastMessageContent()?.let { messageContent ->
                     when (messageContent.msgType) {
                         MessageType.MSGTYPE_TEXT                 -> {
@@ -100,17 +100,17 @@ class DisplayableEventFormatter @Inject constructor(
                     }
                 } ?: span { }
             }
-            EventType.STICKER               -> {
+            EventType.STICKER                   -> {
                 simpleFormat(senderName, stringProvider.getString(R.string.send_a_sticker), appendAuthor)
             }
-            EventType.REACTION              -> {
+            EventType.REACTION                  -> {
                 timelineEvent.root.getClearContent().toModel()?.relatesTo?.let {
                     val emojiSpanned = emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
                     simpleFormat(senderName, emojiSpanned, appendAuthor)
                 } ?: span { }
             }
             EventType.KEY_VERIFICATION_CANCEL,
-            EventType.KEY_VERIFICATION_DONE -> {
+            EventType.KEY_VERIFICATION_DONE     -> {
                 // cancel and done can appear in timeline, so should have representation
                 simpleFormat(senderName, stringProvider.getString(R.string.sent_verification_conclusion), appendAuthor)
             }
@@ -119,20 +119,23 @@ class DisplayableEventFormatter @Inject constructor(
             EventType.KEY_VERIFICATION_MAC,
             EventType.KEY_VERIFICATION_KEY,
             EventType.KEY_VERIFICATION_READY,
-            EventType.CALL_CANDIDATES       -> {
+            EventType.CALL_CANDIDATES           -> {
                 span { }
             }
-            in EventType.POLL_START         -> {
+            in EventType.POLL_START             -> {
                 timelineEvent.root.getClearContent().toModel(catchError = true)?.getBestPollCreationInfo()?.question?.getBestQuestion()
                         ?: stringProvider.getString(R.string.sent_a_poll)
             }
-            in EventType.POLL_RESPONSE      -> {
+            in EventType.POLL_RESPONSE          -> {
                 stringProvider.getString(R.string.poll_response_room_list_preview)
             }
-            in EventType.POLL_END           -> {
+            in EventType.POLL_END               -> {
                 stringProvider.getString(R.string.poll_end_room_list_preview)
             }
-            else                            -> {
+            in EventType.STATE_ROOM_BEACON_INFO -> {
+                simpleFormat(senderName, stringProvider.getString(R.string.sent_live_location), appendAuthor)
+            }
+            else                                -> {
                 span {
                     text = noticeEventFormatter.format(timelineEvent, isDm) ?: ""
                     textStyle = "italic"
@@ -167,7 +170,7 @@ class DisplayableEventFormatter @Inject constructor(
         }
 
         return when (event.getClearType()) {
-            EventType.MESSAGE       -> {
+            EventType.MESSAGE                   -> {
                 (event.getClearContent().toModel() as? MessageContent)?.let { messageContent ->
                     when (messageContent.msgType) {
                         MessageType.MSGTYPE_TEXT                 -> {
@@ -208,25 +211,28 @@ class DisplayableEventFormatter @Inject constructor(
                     }
                 } ?: span { }
             }
-            EventType.STICKER       -> {
+            EventType.STICKER                   -> {
                 stringProvider.getString(R.string.send_a_sticker)
             }
-            EventType.REACTION      -> {
+            EventType.REACTION                  -> {
                 event.getClearContent().toModel()?.relatesTo?.let {
                     emojiSpanify.spanify(stringProvider.getString(R.string.sent_a_reaction, it.key))
                 } ?: span { }
             }
-            in EventType.POLL_START    -> {
+            in EventType.POLL_START             -> {
                 event.getClearContent().toModel(catchError = true)?.pollCreationInfo?.question?.question
                         ?: stringProvider.getString(R.string.sent_a_poll)
             }
-            in EventType.POLL_RESPONSE -> {
+            in EventType.POLL_RESPONSE          -> {
                 stringProvider.getString(R.string.poll_response_room_list_preview)
             }
-            in EventType.POLL_END      -> {
+            in EventType.POLL_END               -> {
                 stringProvider.getString(R.string.poll_end_room_list_preview)
             }
-            else                    -> {
+            in EventType.STATE_ROOM_BEACON_INFO -> {
+                stringProvider.getString(R.string.sent_live_location)
+            }
+            else                                -> {
                 span {
                 }
             }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
index a20c1e5f971..51dc26247cc 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/format/NoticeEventFormatter.kt
@@ -21,10 +21,12 @@ import im.vector.app.R
 import im.vector.app.core.resources.StringProvider
 import im.vector.app.features.roomprofile.permissions.RoleFormatter
 import im.vector.app.features.settings.VectorPreferences
+import org.matrix.android.sdk.api.crypto.MXCRYPTO_ALGORITHM_MEGOLM
 import org.matrix.android.sdk.api.extensions.appendNl
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.events.model.Event
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptionEventContent
 import org.matrix.android.sdk.api.session.events.model.isThread
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.GuestAccess
@@ -47,8 +49,6 @@ import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
 import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.widgets.model.WidgetContent
-import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptionEventContent
 import timber.log.Timber
 import javax.inject.Inject
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/AudioMessagePlaybackTracker.kt
similarity index 85%
rename from vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt
rename to vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/AudioMessagePlaybackTracker.kt
index 8167ad94aff..0312ac9e6fc 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/VoiceMessagePlaybackTracker.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/AudioMessagePlaybackTracker.kt
@@ -22,7 +22,7 @@ import javax.inject.Inject
 import javax.inject.Singleton
 
 @Singleton
-class VoiceMessagePlaybackTracker @Inject constructor() {
+class AudioMessagePlaybackTracker @Inject constructor() {
 
     private val mainHandler = Handler(Looper.getMainLooper())
     private val listeners = mutableMapOf()
@@ -33,7 +33,7 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
         activityListeners.add(listener)
     }
 
-    fun unTrackActivity(listener: ActivityListener) {
+    fun untrackActivity(listener: ActivityListener) {
         activityListeners.remove(listener)
     }
 
@@ -46,10 +46,16 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
         }
     }
 
-    fun unTrack(id: String) {
+    fun untrack(id: String) {
         listeners.remove(id)
     }
 
+    fun pauseAllPlaybacks() {
+        listeners.keys.forEach { key ->
+            pausePlayback(key)
+        }
+    }
+
     fun makeAllPlaybacksIdle() {
         listeners.keys.forEach { key ->
             setState(key, Listener.State.Idle)
@@ -87,19 +93,25 @@ class VoiceMessagePlaybackTracker @Inject constructor() {
     }
 
     fun pausePlayback(id: String) {
-        val currentPlaybackTime = getPlaybackTime(id)
-        val currentPercentage = getPercentage(id)
-        setState(id, Listener.State.Paused(currentPlaybackTime, currentPercentage))
+        if (getPlaybackState(id) is Listener.State.Playing) {
+            val currentPlaybackTime = getPlaybackTime(id)
+            val currentPercentage = getPercentage(id)
+            setState(id, Listener.State.Paused(currentPlaybackTime, currentPercentage))
+        }
     }
 
     fun stopPlayback(id: String) {
         setState(id, Listener.State.Idle)
     }
 
-    fun updateCurrentPlaybackTime(id: String, time: Int, percentage: Float) {
+    fun updatePlayingAtPlaybackTime(id: String, time: Int, percentage: Float) {
         setState(id, Listener.State.Playing(time, percentage))
     }
 
+    fun updatePausedAtPlaybackTime(id: String, time: Int, percentage: Float) {
+        setState(id, Listener.State.Paused(time, percentage))
+    }
+
     fun updateCurrentRecording(id: String, amplitudeList: List) {
         setState(id, Listener.State.Recording(amplitudeList))
     }
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt
index 97b3a8f445f..f882840eee2 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/MessageInformationDataFactory.kt
@@ -27,10 +27,11 @@ import im.vector.app.features.home.room.detail.timeline.item.PollVoteSummaryData
 import im.vector.app.features.home.room.detail.timeline.item.ReferencesInfoData
 import im.vector.app.features.home.room.detail.timeline.item.SendStateDecoration
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayoutFactory
-import org.matrix.android.sdk.api.crypto.VerificationState
 import org.matrix.android.sdk.api.extensions.orFalse
 import org.matrix.android.sdk.api.session.Session
+import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
 import org.matrix.android.sdk.api.session.events.model.EventType
+import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
 import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
 import org.matrix.android.sdk.api.session.events.model.toModel
 import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
@@ -40,7 +41,6 @@ import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
 import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
 import org.matrix.android.sdk.api.session.room.timeline.hasBeenEdited
-import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
 import javax.inject.Inject
 
 /**
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt
index 96a2ca4609d..1736b20d445 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/helper/TimelineDisplayableEvents.kt
@@ -50,8 +50,8 @@ object TimelineDisplayableEvents {
             EventType.STATE_ROOM_TOMBSTONE,
             EventType.STATE_ROOM_JOIN_RULES,
             EventType.KEY_VERIFICATION_DONE,
-            EventType.KEY_VERIFICATION_CANCEL
-    ) + EventType.POLL_START
+            EventType.KEY_VERIFICATION_CANCEL,
+    ) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
 }
 
 fun TimelineEvent.canBeMerged(): Boolean {
@@ -71,7 +71,7 @@ fun TimelineEvent.isRoomConfiguration(roomCreatorUserId: String?): Boolean {
         EventType.STATE_ROOM_CANONICAL_ALIAS,
         EventType.STATE_ROOM_POWER_LEVELS,
         EventType.STATE_ROOM_ENCRYPTION -> true
-        EventType.STATE_ROOM_MEMBER -> {
+        EventType.STATE_ROOM_MEMBER     -> {
             // Keep only room member events regarding the room creator (when he joined the room),
             // but exclude events where the room creator invite others, or where others join
             roomCreatorUserId != null && root.stateKey == roomCreatorUserId
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt
index 2ad58df3b86..26cab4d863a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/image/ImageContentRendererFactory.kt
@@ -17,6 +17,7 @@
 package im.vector.app.features.home.room.detail.timeline.image
 
 import im.vector.app.features.media.ImageContentRenderer
+import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt
 import org.matrix.android.sdk.api.session.events.model.isImageMessage
 import org.matrix.android.sdk.api.session.events.model.isVideoMessage
 import org.matrix.android.sdk.api.session.events.model.toModel
@@ -25,7 +26,6 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
 import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
 import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
 import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
-import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
 
 fun TimelineEvent.buildImageContentRendererData(maxHeight: Int): ImageContentRenderer.Data? {
     return when {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
index 4f08c9d05f8..c21cb5319e0 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/AbsBaseMessageItem.kt
@@ -39,7 +39,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController
 import im.vector.app.features.home.room.detail.timeline.view.TimelineMessageLayoutRenderer
 import im.vector.app.features.reactions.widget.ReactionButton
 import im.vector.app.features.themes.ThemeUtils
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import org.matrix.android.sdk.api.session.room.send.SendState
 
 private const val MAX_REACTIONS_TO_SHOW = 8
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt
index 9f631f7a0ea..f3ca5251361 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MergedRoomCreationItem.kt
@@ -133,7 +133,10 @@ abstract class MergedRoomCreationItem : BasedMergedItem() {
+
+    @EpoxyAttribute
+    var filename: String = ""
+
+    @EpoxyAttribute
+    var mxcUrl: String = ""
+
+    @EpoxyAttribute
+    var duration: Int = 0
+
+    @EpoxyAttribute
+    var fileSize: Long = 0
+
+    @EpoxyAttribute
+    @JvmField
+    var isLocalFile = false
+
+    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+    var onSeek: ((percentage: Float) -> Unit)? = null
+
+    @EpoxyAttribute
+    lateinit var contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder
+
+    @EpoxyAttribute
+    lateinit var contentDownloadStateTrackerBinder: ContentDownloadStateTrackerBinder
+
+    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
+    var playbackControlButtonClickListener: ClickListener? = null
+
+    @EpoxyAttribute
+    lateinit var audioMessagePlaybackTracker: AudioMessagePlaybackTracker
+
+    private var isUserSeeking = false
+
+    override fun bind(holder: Holder) {
+        super.bind(holder)
+        renderSendState(holder.rootLayout, null)
+        bindViewAttributes(holder)
+        bindUploadState(holder)
+        applyLayoutTint(holder)
+        bindSeekBar(holder)
+        holder.audioPlaybackControlButton.setOnClickListener { playbackControlButtonClickListener?.invoke(it) }
+        renderStateBasedOnAudioPlayback(holder)
+    }
+
+    private fun bindUploadState(holder: Holder) {
+        if (attributes.informationData.sendState.hasFailed()) {
+            holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_cross)
+            holder.audioPlaybackControlButton.contentDescription =
+                    holder.view.context.getString(R.string.error_audio_message_unable_to_play, filename)
+            holder.progressLayout.isVisible = false
+        } else {
+            contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, isLocalFile, holder.progressLayout)
+        }
+    }
+
+    private fun applyLayoutTint(holder: Holder) {
+        val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) {
+            Color.TRANSPARENT
+        } else {
+            ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quinary)
+        }
+        holder.mainLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint)
+    }
+
+    private fun bindViewAttributes(holder: Holder) {
+        val formattedDuration = formatPlaybackTime(duration)
+        val formattedFileSize = TextUtils.formatFileSize(holder.rootLayout.context, fileSize, true)
+        val durationContentDescription = getPlaybackTimeContentDescription(holder.rootLayout.context, duration)
+
+        holder.filenameView.text = filename
+        holder.filenameView.onClick(attributes.itemClickListener)
+        holder.audioPlaybackDuration.text = formattedDuration
+        holder.fileSize.text = holder.rootLayout.context.getString(
+                R.string.audio_message_file_size, formattedFileSize
+        )
+        holder.mainLayout.contentDescription = holder.rootLayout.context.getString(
+                R.string.a11y_audio_message_item, filename, durationContentDescription, formattedFileSize
+        )
+    }
+
+    private fun bindSeekBar(holder: Holder) {
+        holder.audioSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+            override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+                holder.audioPlaybackTime.text = formatPlaybackTime(
+                        (duration * (progress.toFloat() / 100)).toInt()
+                )
+            }
+            override fun onStartTrackingTouch(seekBar: SeekBar) {
+                isUserSeeking = true
+            }
+            override fun onStopTrackingTouch(seekBar: SeekBar) {
+                isUserSeeking = false
+                val percentage = seekBar.progress.toFloat() / 100
+                onSeek?.invoke(percentage)
+            }
+        })
+    }
+
+    private fun renderStateBasedOnAudioPlayback(holder: Holder) {
+        audioMessagePlaybackTracker.track(attributes.informationData.eventId, object : AudioMessagePlaybackTracker.Listener {
+            override fun onUpdate(state: AudioMessagePlaybackTracker.Listener.State) {
+                when (state) {
+                    is AudioMessagePlaybackTracker.Listener.State.Idle      -> renderIdleState(holder)
+                    is AudioMessagePlaybackTracker.Listener.State.Playing   -> renderPlayingState(holder, state)
+                    is AudioMessagePlaybackTracker.Listener.State.Paused    -> renderPausedState(holder, state)
+                    is AudioMessagePlaybackTracker.Listener.State.Recording -> Unit
+                }
+            }
+        })
+    }
+
+    private fun renderIdleState(holder: Holder) {
+        holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
+        holder.audioPlaybackControlButton.contentDescription =
+                holder.view.context.getString(R.string.a11y_play_audio_message, filename)
+        holder.audioPlaybackTime.text = formatPlaybackTime(duration)
+        holder.audioSeekBar.progress = 0
+    }
+
+    private fun renderPlayingState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Playing) {
+        holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
+        holder.audioPlaybackControlButton.contentDescription =
+                holder.view.context.getString(R.string.a11y_pause_audio_message, filename)
+
+        if (!isUserSeeking) {
+            holder.audioPlaybackTime.text = formatPlaybackTime(state.playbackTime)
+            holder.audioSeekBar.progress = (state.percentage * 100).toInt()
+        }
+    }
+
+    private fun renderPausedState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Paused) {
+        holder.audioPlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
+        holder.audioPlaybackControlButton.contentDescription =
+                holder.view.context.getString(R.string.a11y_play_audio_message, filename)
+        holder.audioPlaybackTime.text = formatPlaybackTime(state.playbackTime)
+        holder.audioSeekBar.progress = (state.percentage * 100).toInt()
+    }
+
+    private fun formatPlaybackTime(time: Int) = DateUtils.formatElapsedTime((time / 1000).toLong())
+
+    private fun getPlaybackTimeContentDescription(context: Context, time: Int): String {
+        val formattedPlaybackTime = formatPlaybackTime(time)
+        val (minutes, seconds) = formattedPlaybackTime.split(":").map { it.toIntOrNull() ?: 0 }
+        return context.getString(R.string.a11y_audio_playback_duration, minutes, seconds)
+    }
+
+    override fun unbind(holder: Holder) {
+        super.unbind(holder)
+        contentUploadStateTrackerBinder.unbind(attributes.informationData.eventId)
+        contentDownloadStateTrackerBinder.unbind(mxcUrl)
+        audioMessagePlaybackTracker.untrack(attributes.informationData.eventId)
+    }
+
+    override fun getViewStubId() = STUB_ID
+
+    class Holder : AbsMessageItem.Holder(STUB_ID) {
+        val rootLayout by bind(R.id.messageRootLayout)
+        val mainLayout by bind(R.id.messageMainInnerLayout)
+        val filenameView by bind(R.id.messageFilenameView)
+        val audioPlaybackControlButton by bind(R.id.audioPlaybackControlButton)
+        val audioPlaybackTime by bind(R.id.audioPlaybackTime)
+        val progressLayout by bind(R.id.messageFileUploadProgressLayout)
+        val fileSize by bind(R.id.fileSize)
+        val audioPlaybackDuration by bind(R.id.audioPlaybackDuration)
+        val audioSeekBar by bind(R.id.audioSeekBar)
+    }
+
+    companion object {
+        private const val STUB_ID = R.id.messageContentAudioStub
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
index 8b6899daee4..8a94f927f9f 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageFileItem.kt
@@ -47,14 +47,13 @@ abstract class MessageFileItem : AbsMessageItem() {
     @DrawableRes
     var iconRes: Int = 0
 
-//    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
-//    var clickListener: ClickListener? = null
-
     @EpoxyAttribute
-    var izLocalFile = false
+    @JvmField
+    var isLocalFile = false
 
     @EpoxyAttribute
-    var izDownloaded = false
+    @JvmField
+    var isDownloaded = false
 
     @EpoxyAttribute
     lateinit var contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder
@@ -65,17 +64,20 @@ abstract class MessageFileItem : AbsMessageItem() {
     override fun bind(holder: Holder) {
         super.bind(holder)
         renderSendState(holder.fileLayout, holder.filenameView)
+
         if (!attributes.informationData.sendState.hasFailed()) {
-            contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout)
+            contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, isLocalFile, holder.progressLayout)
         } else {
             holder.fileImageView.setImageResource(R.drawable.ic_cross)
             holder.progressLayout.isVisible = false
         }
+
         holder.filenameView.text = filename
+
         if (attributes.informationData.sendState.isSending()) {
             holder.fileImageView.setImageResource(iconRes)
         } else {
-            if (izDownloaded) {
+            if (isDownloaded) {
                 holder.fileImageView.setImageResource(iconRes)
                 holder.fileDownloadProgress.progress = 0
             } else {
@@ -83,7 +85,7 @@ abstract class MessageFileItem : AbsMessageItem() {
                 holder.fileImageView.setImageResource(R.drawable.ic_download)
             }
         }
-//        holder.view.setOnClickListener(clickListener)
+
         val backgroundTint = if (attributes.informationData.messageLayout is TimelineMessageLayout.Bubble) {
             Color.TRANSPARENT
         } else {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt
index 04b558b14fa..9620077fd82 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageInformationData.kt
@@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.item
 import android.os.Parcelable
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
 import kotlinx.parcelize.Parcelize
-import org.matrix.android.sdk.api.crypto.VerificationState
+import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
 import org.matrix.android.sdk.api.session.room.send.SendState
 import org.matrix.android.sdk.api.util.MatrixItem
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLiveLocationStartItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLiveLocationStartItem.kt
new file mode 100644
index 00000000000..390db0ef508
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageLiveLocationStartItem.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2022 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.features.home.room.detail.timeline.item
+
+import android.graphics.drawable.ColorDrawable
+import android.widget.ImageView
+import androidx.core.view.updateLayoutParams
+import com.airbnb.epoxy.EpoxyAttribute
+import com.airbnb.epoxy.EpoxyModelClass
+import com.bumptech.glide.load.resource.bitmap.GranularRoundedCorners
+import com.bumptech.glide.load.resource.bitmap.RoundedCorners
+import im.vector.app.R
+import im.vector.app.core.glide.GlideApp
+import im.vector.app.core.utils.DimensionConverter
+import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
+import im.vector.app.features.home.room.detail.timeline.style.granularRoundedCorners
+import im.vector.app.features.themes.ThemeUtils
+
+@EpoxyModelClass(layout = R.layout.item_timeline_event_base)
+abstract class MessageLiveLocationStartItem : AbsMessageItem() {
+
+    @EpoxyAttribute
+    var mapWidth: Int = 0
+
+    @EpoxyAttribute
+    var mapHeight: Int = 0
+
+    override fun bind(holder: Holder) {
+        super.bind(holder)
+        renderSendState(holder.view, null)
+        bindMap(holder)
+        bindBottomBanner(holder)
+    }
+
+    private fun bindMap(holder: Holder) {
+        val messageLayout = attributes.informationData.messageLayout
+        val mapCornerTransformation = if (messageLayout is TimelineMessageLayout.Bubble) {
+            messageLayout.cornersRadius.granularRoundedCorners()
+        } else {
+            RoundedCorners(getDefaultLayoutCornerRadiusInDp(holder))
+        }
+        holder.noLocationMapImageView.updateLayoutParams {
+            width = mapWidth
+            height = mapHeight
+        }
+        GlideApp.with(holder.noLocationMapImageView)
+                .load(R.drawable.bg_no_location_map)
+                .transform(mapCornerTransformation)
+                .into(holder.noLocationMapImageView)
+    }
+
+    private fun bindBottomBanner(holder: Holder) {
+        val messageLayout = attributes.informationData.messageLayout
+        val imageCornerTransformation = if (messageLayout is TimelineMessageLayout.Bubble) {
+            GranularRoundedCorners(0f, 0f, messageLayout.cornersRadius.bottomEndRadius, messageLayout.cornersRadius.bottomStartRadius)
+        } else {
+            val bottomCornerRadius = getDefaultLayoutCornerRadiusInDp(holder).toFloat()
+            GranularRoundedCorners(0f, 0f, bottomCornerRadius, bottomCornerRadius)
+        }
+        GlideApp.with(holder.bannerImageView)
+                .load(ColorDrawable(ThemeUtils.getColor(holder.bannerImageView.context, R.attr.colorSurface)))
+                .transform(imageCornerTransformation)
+                .into(holder.bannerImageView)
+    }
+
+    private fun getDefaultLayoutCornerRadiusInDp(holder: Holder): Int {
+        val dimensionConverter = DimensionConverter(holder.view.resources)
+        return dimensionConverter.dpToPx(8)
+    }
+
+    override fun getViewStubId() = STUB_ID
+
+    class Holder : AbsMessageItem.Holder(STUB_ID) {
+        val bannerImageView by bind(R.id.locationLiveStartBanner)
+        val noLocationMapImageView by bind(R.id.locationLiveStartMap)
+    }
+
+    companion object {
+        private const val STUB_ID = R.id.messageContentLiveLocationStartStub
+    }
+}
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
index aad30ef41ed..02937574f2a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/MessageVoiceItem.kt
@@ -30,9 +30,9 @@ import com.airbnb.epoxy.EpoxyAttribute
 import com.airbnb.epoxy.EpoxyModelClass
 import im.vector.app.R
 import im.vector.app.core.epoxy.ClickListener
+import im.vector.app.features.home.room.detail.timeline.helper.AudioMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
 import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
-import im.vector.app.features.home.room.detail.timeline.helper.VoiceMessagePlaybackTracker
 import im.vector.app.features.home.room.detail.timeline.style.TimelineMessageLayout
 import im.vector.app.features.themes.ThemeUtils
 import im.vector.app.features.voice.AudioWaveformView
@@ -55,10 +55,8 @@ abstract class MessageVoiceItem : AbsMessageItem() {
     var waveform: List = emptyList()
 
     @EpoxyAttribute
-    var izLocalFile = false
-
-    @EpoxyAttribute
-    var izDownloaded = false
+    @JvmField
+    var isLocalFile = false
 
     @EpoxyAttribute
     lateinit var contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder
@@ -73,13 +71,13 @@ abstract class MessageVoiceItem : AbsMessageItem() {
     var waveformTouchListener: WaveformTouchListener? = null
 
     @EpoxyAttribute
-    lateinit var voiceMessagePlaybackTracker: VoiceMessagePlaybackTracker
+    lateinit var audioMessagePlaybackTracker: AudioMessagePlaybackTracker
 
     override fun bind(holder: Holder) {
         super.bind(holder)
         renderSendState(holder.voiceLayout, null)
         if (!attributes.informationData.sendState.hasFailed()) {
-            contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, izLocalFile, holder.progressLayout)
+            contentUploadStateTrackerBinder.bind(attributes.informationData.eventId, isLocalFile, holder.progressLayout)
         } else {
             holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_cross)
             holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.error_voice_message_unable_to_play)
@@ -96,11 +94,11 @@ abstract class MessageVoiceItem : AbsMessageItem() {
             ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quinary)
         }
         holder.voicePlaybackLayout.backgroundTintList = ColorStateList.valueOf(backgroundTint)
-        holder.voicePlaybackControlButton.setOnClickListener { playbackControlButtonClickListener?.invoke(it) }
     }
 
     private fun onWaveformViewReady(holder: Holder) {
         holder.voicePlaybackWaveform.setOnLongClickListener(attributes.itemLongClickListener)
+        holder.voicePlaybackControlButton.setOnClickListener { playbackControlButtonClickListener?.invoke(it) }
 
         val waveformColorIdle = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_quaternary)
         val waveformColorPlayed = ThemeUtils.getColor(holder.view.context, R.attr.vctr_content_secondary)
@@ -125,13 +123,13 @@ abstract class MessageVoiceItem : AbsMessageItem() {
             true
         }
 
-        voiceMessagePlaybackTracker.track(attributes.informationData.eventId, object : VoiceMessagePlaybackTracker.Listener {
-            override fun onUpdate(state: VoiceMessagePlaybackTracker.Listener.State) {
+        audioMessagePlaybackTracker.track(attributes.informationData.eventId, object : AudioMessagePlaybackTracker.Listener {
+            override fun onUpdate(state: AudioMessagePlaybackTracker.Listener.State) {
                 when (state) {
-                    is VoiceMessagePlaybackTracker.Listener.State.Idle    -> renderIdleState(holder, waveformColorIdle, waveformColorPlayed)
-                    is VoiceMessagePlaybackTracker.Listener.State.Playing -> renderPlayingState(holder, state, waveformColorIdle, waveformColorPlayed)
-                    is VoiceMessagePlaybackTracker.Listener.State.Paused  -> renderPausedState(holder, state, waveformColorIdle, waveformColorPlayed)
-                    is VoiceMessagePlaybackTracker.Listener.State.Recording -> Unit
+                    is AudioMessagePlaybackTracker.Listener.State.Idle    -> renderIdleState(holder, waveformColorIdle, waveformColorPlayed)
+                    is AudioMessagePlaybackTracker.Listener.State.Playing -> renderPlayingState(holder, state, waveformColorIdle, waveformColorPlayed)
+                    is AudioMessagePlaybackTracker.Listener.State.Paused  -> renderPausedState(holder, state, waveformColorIdle, waveformColorPlayed)
+                    is AudioMessagePlaybackTracker.Listener.State.Recording -> Unit
                 }
             }
         })
@@ -146,14 +144,14 @@ abstract class MessageVoiceItem : AbsMessageItem() {
         holder.voicePlaybackWaveform.updateColors(0f, playedColor, idleColor)
     }
 
-    private fun renderPlayingState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Playing, idleColor: Int, playedColor: Int) {
+    private fun renderPlayingState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Playing, idleColor: Int, playedColor: Int) {
         holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_pause)
         holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_pause_voice_message)
         holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
         holder.voicePlaybackWaveform.updateColors(state.percentage, playedColor, idleColor)
     }
 
-    private fun renderPausedState(holder: Holder, state: VoiceMessagePlaybackTracker.Listener.State.Paused, idleColor: Int, playedColor: Int) {
+    private fun renderPausedState(holder: Holder, state: AudioMessagePlaybackTracker.Listener.State.Paused, idleColor: Int, playedColor: Int) {
         holder.voicePlaybackControlButton.setImageResource(R.drawable.ic_play_pause_play)
         holder.voicePlaybackControlButton.contentDescription = holder.view.context.getString(R.string.a11y_play_voice_message)
         holder.voicePlaybackTime.text = formatPlaybackTime(state.playbackTime)
@@ -166,7 +164,7 @@ abstract class MessageVoiceItem : AbsMessageItem() {
         super.unbind(holder)
         contentUploadStateTrackerBinder.unbind(attributes.informationData.eventId)
         contentDownloadStateTrackerBinder.unbind(mxcUrl)
-        voiceMessagePlaybackTracker.unTrack(attributes.informationData.eventId)
+        audioMessagePlaybackTracker.untrack(attributes.informationData.eventId)
     }
 
     override fun getViewStubId() = STUB_ID
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt
index 3c3510a073f..7ca5166542a 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/NoticeItem.kt
@@ -28,7 +28,7 @@ import im.vector.app.core.ui.views.ShieldImageView
 import im.vector.app.features.home.AvatarRenderer
 import im.vector.app.features.home.room.detail.timeline.TimelineEventController
 import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 
 @EpoxyModelClass(layout = R.layout.item_timeline_event_base_noinfo)
 abstract class NoticeItem : BaseEventItem() {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
index 61fcddd1238..0e6530fdca2 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/VerificationRequestItem.kt
@@ -35,8 +35,8 @@ import im.vector.app.features.home.AvatarRenderer
 import im.vector.app.features.home.room.detail.RoomDetailAction
 import im.vector.app.features.home.room.detail.timeline.MessageColorProvider
 import im.vector.app.features.home.room.detail.timeline.TimelineEventController
-import org.matrix.android.sdk.api.crypto.VerificationState
 import org.matrix.android.sdk.api.session.crypto.verification.VerificationService
+import org.matrix.android.sdk.api.session.crypto.verification.VerificationState
 
 @EpoxyModelClass(layout = R.layout.item_timeline_event_base_state)
 abstract class VerificationRequestItem : AbsBaseMessageItem() {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt
index c0e668e0139..ae9b004f6ce 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayout.kt
@@ -38,19 +38,20 @@ sealed interface TimelineMessageLayout : Parcelable {
 
     @Parcelize
     data class Bubble(
-        override val showAvatar: Boolean,
-        override val showDisplayName: Boolean,
-        override val showTimestamp: Boolean = true,
-        val addTopMargin: Boolean = false,
-        val isIncoming: Boolean,
-        val isPseudoBubble: Boolean,
-        val cornersRadius: CornersRadius,
-        val timestampAsOverlay: Boolean,
-        override val layoutRes: Int = if (isIncoming) {
-            R.layout.item_timeline_event_bubble_incoming_base
-        } else {
-            R.layout.item_timeline_event_bubble_outgoing_base
-        },
+            override val showAvatar: Boolean,
+            override val showDisplayName: Boolean,
+            override val showTimestamp: Boolean = true,
+            val addTopMargin: Boolean = false,
+            val isIncoming: Boolean,
+            val isPseudoBubble: Boolean,
+            val cornersRadius: CornersRadius,
+            val timestampInsideMessage: Boolean,
+            val addMessageOverlay: Boolean,
+            override val layoutRes: Int = if (isIncoming) {
+                R.layout.item_timeline_event_bubble_incoming_base
+            } else {
+                R.layout.item_timeline_event_bubble_outgoing_base
+            },
     ) : TimelineMessageLayout {
 
         @Parcelize
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt
index 04430bf69f8..f2334e5a4f7 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/style/TimelineMessageLayoutFactory.kt
@@ -46,7 +46,7 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess
                 EventType.MESSAGE,
                 EventType.ENCRYPTED,
                 EventType.STICKER
-        ) + EventType.POLL_START
+        ) + EventType.POLL_START + EventType.STATE_ROOM_BEACON_INFO
 
         // Can't be rendered in bubbles, so get back to default layout
         private val MSG_TYPES_WITHOUT_BUBBLE_LAYOUT = setOf(
@@ -58,10 +58,13 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess
                 MessageType.MSGTYPE_IMAGE,
                 MessageType.MSGTYPE_VIDEO,
                 MessageType.MSGTYPE_STICKER_LOCAL,
-                MessageType.MSGTYPE_EMOTE
+                MessageType.MSGTYPE_EMOTE,
+                MessageType.MSGTYPE_LIVE_LOCATION_STATE,
         )
-        private val MSG_TYPES_WITH_TIMESTAMP_AS_OVERLAY = setOf(
-                MessageType.MSGTYPE_IMAGE, MessageType.MSGTYPE_VIDEO
+        private val MSG_TYPES_WITH_TIMESTAMP_INSIDE_MESSAGE = setOf(
+                MessageType.MSGTYPE_IMAGE,
+                MessageType.MSGTYPE_VIDEO,
+                MessageType.MSGTYPE_LIVE_LOCATION_STATE,
         )
     }
 
@@ -70,7 +73,7 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess
     }
 
     private val isRTL: Boolean by lazy {
-       localeProvider.isRTL()
+        localeProvider.isRTL()
     }
 
     fun create(params: TimelineItemFactoryParams): TimelineMessageLayout {
@@ -123,7 +126,8 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess
                             isIncoming = !isSentByMe,
                             cornersRadius = cornersRadius,
                             isPseudoBubble = messageContent.isPseudoBubble(),
-                            timestampAsOverlay = messageContent.timestampAsOverlay()
+                            timestampInsideMessage = messageContent.timestampInsideMessage(),
+                            addMessageOverlay = messageContent.shouldAddMessageOverlay(),
                     )
                 } else {
                     buildModernLayout(showInformation)
@@ -139,10 +143,18 @@ class TimelineMessageLayoutFactory @Inject constructor(private val session: Sess
         return this.msgType in MSG_TYPES_WITH_PSEUDO_BUBBLE_LAYOUT
     }
 
-    private fun MessageContent?.timestampAsOverlay(): Boolean {
+    private fun MessageContent?.timestampInsideMessage(): Boolean {
         if (this == null) return false
         if (msgType == MessageType.MSGTYPE_LOCATION) return vectorPreferences.labsRenderLocationsInTimeline()
-        return this.msgType in MSG_TYPES_WITH_TIMESTAMP_AS_OVERLAY
+        return this.msgType in MSG_TYPES_WITH_TIMESTAMP_INSIDE_MESSAGE
+    }
+
+    private fun MessageContent?.shouldAddMessageOverlay(): Boolean {
+        return when {
+            this == null || msgType == MessageType.MSGTYPE_LIVE_LOCATION_STATE -> false
+            msgType == MessageType.MSGTYPE_LOCATION                            -> vectorPreferences.labsRenderLocationsInTimeline()
+            else                                                               -> msgType in MSG_TYPES_WITH_TIMESTAMP_INSIDE_MESSAGE
+        }
     }
 
     private fun TimelineEvent.shouldBuildBubbleLayout(): Boolean {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt
index 954aa0bf346..87ed9243a55 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/view/MessageBubbleView.kt
@@ -43,9 +43,9 @@ import im.vector.app.features.themes.ThemeUtils
 import timber.log.Timber
 
 class MessageBubbleView @JvmOverloads constructor(
-    context: Context,
-    attrs: AttributeSet? = null,
-    defStyleAttr: Int = 0,
+        context: Context,
+        attrs: AttributeSet? = null,
+        defStyleAttr: Int = 0,
 ) : RelativeLayout(context, attrs, defStyleAttr), TimelineMessageLayoutRenderer {
 
     private var isIncoming: Boolean = false
@@ -89,21 +89,21 @@ class MessageBubbleView @JvmOverloads constructor(
             outlineProvider = ViewOutlineProvider.BACKGROUND
             clipToOutline = true
             background = RippleDrawable(
-                ContextCompat.getColorStateList(context, R.color.mtrl_btn_ripple_color) ?: ColorStateList.valueOf(Color.TRANSPARENT),
-                bubbleDrawable,
-                rippleMaskDrawable)
+                    ContextCompat.getColorStateList(context, R.color.mtrl_btn_ripple_color) ?: ColorStateList.valueOf(Color.TRANSPARENT),
+                    bubbleDrawable,
+                    rippleMaskDrawable)
         }
     }
 
     override fun renderMessageLayout(messageLayout: TimelineMessageLayout) {
         (messageLayout as? TimelineMessageLayout.Bubble)
-            ?.updateDrawables()
-            ?.setConstraintsAndColor()
-            ?.toggleMessageOverlay()
-            ?.setPadding()
-            ?.setMargins()
-            ?.setAdditionalTopSpace()
-            ?: Timber.v("Can't render messageLayout $messageLayout")
+                ?.updateDrawables()
+                ?.setConstraints()
+                ?.toggleMessageOverlay()
+                ?.setPadding()
+                ?.setMargins()
+                ?.setAdditionalTopSpace()
+                ?: Timber.v("Can't render messageLayout $messageLayout")
     }
 
     private fun TimelineMessageLayout.Bubble.updateDrawables() = apply {
@@ -121,17 +121,13 @@ class MessageBubbleView @JvmOverloads constructor(
         rippleMaskDrawable.shapeAppearanceModel = shapeAppearanceModel
     }
 
-    private fun TimelineMessageLayout.Bubble.setConstraintsAndColor() = apply {
+    private fun TimelineMessageLayout.Bubble.setConstraints() = apply {
         ConstraintSet().apply {
             clone(views.bubbleView)
             clear(R.id.viewStubContainer, ConstraintSet.END)
-            if (timestampAsOverlay) {
-                val timeColor = ContextCompat.getColor(context, R.color.palette_white)
-                views.messageTimeView.setTextColor(timeColor)
+            if (timestampInsideMessage) {
                 connect(R.id.viewStubContainer, ConstraintSet.END, R.id.parent, ConstraintSet.END, 0)
             } else {
-                val timeColor = ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)
-                views.messageTimeView.setTextColor(timeColor)
                 connect(R.id.viewStubContainer, ConstraintSet.END, R.id.messageTimeView, ConstraintSet.START, 0)
             }
             applyTo(views.bubbleView)
@@ -139,16 +135,20 @@ class MessageBubbleView @JvmOverloads constructor(
     }
 
     private fun TimelineMessageLayout.Bubble.toggleMessageOverlay() = apply {
-        if (timestampAsOverlay) {
+        if (addMessageOverlay) {
+            val timeColor = ContextCompat.getColor(context, R.color.palette_white)
+            views.messageTimeView.setTextColor(timeColor)
             views.messageOverlayView.isVisible = true
             (views.messageOverlayView.background as? GradientDrawable)?.cornerRadii = cornersRadius.toFloatArray()
         } else {
+            val timeColor = ThemeUtils.getColor(context, R.attr.vctr_content_tertiary)
+            views.messageTimeView.setTextColor(timeColor)
             views.messageOverlayView.isVisible = false
         }
     }
 
     private fun TimelineMessageLayout.Bubble.setPadding() = apply {
-        if (isPseudoBubble && timestampAsOverlay) {
+        if (isPseudoBubble && timestampInsideMessage) {
             views.viewStubContainer.root.setPadding(0, 0, 0, 0)
         } else {
             views.viewStubContainer.root.setPadding(horizontalStubPadding, verticalStubPadding, horizontalStubPadding, verticalStubPadding)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
index 532385959b3..aaa469f68d3 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomListFragment.kt
@@ -51,7 +51,6 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA
 import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
 import im.vector.app.features.home.room.list.widget.NotifsFabMenuView
 import im.vector.app.features.notifications.NotificationDrawerManager
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt
index b037191ad13..70c5846646c 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItem.kt
@@ -38,7 +38,7 @@ import im.vector.app.features.displayname.getBestName
 import im.vector.app.features.home.AvatarRenderer
 import im.vector.app.features.themes.ThemeUtils
 import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
-import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
+import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel
 import org.matrix.android.sdk.api.session.presence.model.UserPresence
 import org.matrix.android.sdk.api.util.MatrixItem
 
diff --git a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt
index ca2a747b3b1..6326d9c97ad 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/list/RoomSummaryItemFactory.kt
@@ -29,7 +29,6 @@ import im.vector.app.features.home.AvatarRenderer
 import im.vector.app.features.home.room.detail.timeline.format.DisplayableEventFormatter
 import im.vector.app.features.home.room.typing.TypingHelper
 import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence
-import org.matrix.android.sdk.api.MatrixConfiguration
 import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
 import org.matrix.android.sdk.api.session.room.model.Membership
 import org.matrix.android.sdk.api.session.room.model.RoomSummary
@@ -42,8 +41,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
                                                  private val stringProvider: StringProvider,
                                                  private val typingHelper: TypingHelper,
                                                  private val avatarRenderer: AvatarRenderer,
-                                                 private val errorFormatter: ErrorFormatter,
-                                                 private val matrixConfiguration: MatrixConfiguration) {
+                                                 private val errorFormatter: ErrorFormatter) {
 
     fun create(roomSummary: RoomSummary,
                roomChangeMembershipStates: Map,
@@ -127,7 +125,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
                 // We do not display shield in the room list anymore
                 // .encryptionTrustLevel(roomSummary.roomEncryptionTrustLevel)
                 .izPublic(roomSummary.isPublic)
-                .showPresence(roomSummary.isDirect && matrixConfiguration.presenceSyncEnabled)
+                .showPresence(roomSummary.isDirect)
                 .userPresence(roomSummary.directUserPresence)
                 .matrixItem(roomSummary.toMatrixItem())
                 .lastEventTime(latestEventTime)
diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt
index 469a12019a6..545077b5506 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/threads/ThreadsManager.kt
@@ -18,13 +18,14 @@ package im.vector.app.features.home.room.threads
 
 import android.app.Activity
 import android.text.Spanned
+import androidx.annotation.StringRes
 import androidx.core.text.HtmlCompat
 import im.vector.app.R
 import im.vector.app.core.resources.StringProvider
 import im.vector.app.features.MainActivity
 import im.vector.app.features.MainActivityArgs
 import im.vector.app.features.settings.VectorPreferences
-import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage
+import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
 import javax.inject.Inject
 
 /**
@@ -49,11 +50,17 @@ class ThreadsManager @Inject constructor(
     /**
      * Generates and return an Html spanned string to be rendered especially in dialogs
      */
-    fun getBetaEnableThreadsMessage(): Spanned {
+    private fun generateLearnMoreHtmlString(@StringRes messageId: Int): Spanned {
         val learnMore = stringProvider.getString(R.string.action_learn_more)
         val learnMoreUrl = stringProvider.getString(R.string.threads_learn_more_url)
         val href = "$learnMore.

" - val message = stringProvider.getString(R.string.threads_beta_enable_notice_message, href) + val message = stringProvider.getString(messageId, href) return HtmlCompat.fromHtml(message, HtmlCompat.FROM_HTML_MODE_LEGACY) } + + fun getBetaEnableThreadsMessage(): Spanned = + generateLearnMoreHtmlString(R.string.threads_beta_enable_notice_message) + + fun getLabsEnableThreadsMessage(): Spanned = + generateLearnMoreHtmlString(R.string.threads_labs_enable_notice_message) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadListArgs.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadListArgs.kt index aa3746ea418..febd0632027 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadListArgs.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadListArgs.kt @@ -18,7 +18,7 @@ package im.vector.app.features.home.room.threads.arguments import android.os.Parcelable import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @Parcelize data class ThreadListArgs( diff --git a/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadTimelineArgs.kt b/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadTimelineArgs.kt index d3a80811ead..19419e52de2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadTimelineArgs.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/threads/arguments/ThreadTimelineArgs.kt @@ -18,7 +18,7 @@ package im.vector.app.features.home.room.threads.arguments import android.os.Parcelable import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel @Parcelize data class ThreadTimelineArgs( diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt index 063cc3caa6a..2126cdac049 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingService.kt @@ -29,7 +29,7 @@ import im.vector.app.features.session.coroutineScope import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.events.model.EventType.generateBeaconInfoStateEventType +import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.room.model.livelocation.BeaconInfo import org.matrix.android.sdk.api.session.room.model.livelocation.LiveLocationBeaconContent @@ -87,7 +87,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { .getSafeActiveSession() ?.let { session -> session.coroutineScope.launch(session.coroutineDispatchers.io) { - sendBeaconInfo(session, roomArgs) + sendLiveBeaconInfo(session, roomArgs) } } } @@ -95,7 +95,7 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { return START_STICKY } - private suspend fun sendBeaconInfo(session: Session, roomArgs: RoomArgs) { + private suspend fun sendLiveBeaconInfo(session: Session, roomArgs: RoomArgs) { val beaconContent = LiveLocationBeaconContent( unstableBeaconInfo = BeaconInfo( timeout = roomArgs.durationMillis, @@ -104,12 +104,11 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { unstableTimestampAsMilliseconds = clock.epochMillis() ).toContent() - val eventType = generateBeaconInfoStateEventType(session.myUserId) val stateKey = session.myUserId session .getRoom(roomArgs.roomId) ?.sendStateEvent( - eventType = eventType, + eventType = EventType.STATE_ROOM_BEACON_INFO.first(), stateKey = stateKey, body = beaconContent ) @@ -130,8 +129,12 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { } } - private fun stopSharingLocation(roomId: String) { + fun stopSharingLocation(roomId: String) { Timber.i("### LocationSharingService.stopSharingLocation for $roomId") + + // Send a new beacon info state by setting live field as false + sendStoppedBeaconInfo(roomId) + synchronized(roomArgsList) { roomArgsList.removeAll { it.roomId == roomId } if (roomArgsList.isEmpty()) { @@ -141,8 +144,48 @@ class LocationSharingService : VectorService(), LocationTracker.Callback { } } + private fun sendStoppedBeaconInfo(roomId: String) { + activeSessionHolder + .getSafeActiveSession() + ?.let { session -> + session.coroutineScope.launch(session.coroutineDispatchers.io) { + session.getRoom(roomId)?.stopLiveLocation(session.myUserId) + } + } + } + override fun onLocationUpdate(locationData: LocationData) { Timber.i("### LocationSharingService.onLocationUpdate. Uncertainty: ${locationData.uncertainty}") + + val session = activeSessionHolder.getSafeActiveSession() + // Emit location update to all rooms in which live location sharing is active + session?.coroutineScope?.launch(session.coroutineDispatchers.io) { + roomArgsList.toList().forEach { roomArg -> + sendLiveLocation(roomArg.roomId, locationData) + } + } + } + + private suspend fun sendLiveLocation(roomId: String, locationData: LocationData) { + val session = activeSessionHolder.getSafeActiveSession() + val room = session?.getRoom(roomId) + val userId = session?.myUserId + + if (room == null || userId == null) { + return + } + + room + .getLiveLocationBeaconInfo(userId, true) + ?.eventId + ?.let { + room.sendLiveLocation( + beaconInfoEventId = it, + latitude = locationData.latitude, + longitude = locationData.longitude, + uncertainty = locationData.uncertainty + ) + } } override fun onLocationProviderIsNotAvailable() { diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt index 9af6b1539aa..e72f77531bd 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingServiceConnection.kt @@ -34,6 +34,7 @@ class LocationSharingServiceConnection @Inject constructor( private var callback: Callback? = null private var isBound = false + private var locationSharingService: LocationSharingService? = null fun bind(callback: Callback) { this.callback = callback @@ -51,13 +52,19 @@ class LocationSharingServiceConnection @Inject constructor( callback = null } + fun stopLiveLocationSharing(roomId: String) { + locationSharingService?.stopSharingLocation(roomId) + } + override fun onServiceConnected(className: ComponentName, binder: IBinder) { + locationSharingService = (binder as LocationSharingService.LocalBinder).getService() isBound = true callback?.onLocationServiceRunning() } override fun onServiceDisconnected(className: ComponentName) { isBound = false + locationSharingService = null callback?.onLocationServiceStopped() } } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginAction.kt b/vector/src/main/java/im/vector/app/features/login/LoginAction.kt index 70ca49a10e5..800df32b9dd 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginAction.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginAction.kt @@ -20,7 +20,7 @@ import im.vector.app.core.platform.VectorViewModelAction import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider import org.matrix.android.sdk.api.auth.registration.RegisterThreePid -import org.matrix.android.sdk.internal.network.ssl.Fingerprint +import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed class LoginAction : VectorViewModelAction { data class OnGetStarted(val resetLoginConfig: Boolean) : LoginAction() diff --git a/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt index fd180c4f976..45b6e5b8cd6 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginCaptchaFragment.kt @@ -37,7 +37,7 @@ import im.vector.app.R import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginCaptchaBinding import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder import java.util.Formatter @@ -171,7 +171,7 @@ class LoginCaptchaFragment @Inject constructor( try { // URL decode json = URLDecoder.decode(json, "UTF-8") - javascriptResponse = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java).fromJson(json) + javascriptResponse = MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java).fromJson(json) } catch (e: Exception) { Timber.e(e, "## shouldOverrideUrlLoading(): failed") } diff --git a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt index bb73ed79b25..b55e3933396 100644 --- a/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/LoginWebFragment.kt @@ -38,7 +38,7 @@ import im.vector.app.databinding.FragmentLoginWebBinding import im.vector.app.features.signout.soft.SoftLogoutAction import im.vector.app.features.signout.soft.SoftLogoutViewModel import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder import javax.inject.Inject @@ -203,7 +203,7 @@ class LoginWebFragment @Inject constructor( try { // URL decode json = URLDecoder.decode(json, "UTF-8") - val adapter = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java) + val adapter = MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java) javascriptResponse = adapter.fromJson(json) } catch (e: Exception) { Timber.e(e, "## shouldOverrideUrlLoading() : fromJson failed") diff --git a/vector/src/main/java/im/vector/app/features/login/terms/LocalizedFlowDataLoginTermsChecked.kt b/vector/src/main/java/im/vector/app/features/login/terms/LocalizedFlowDataLoginTermsChecked.kt index e6b082ceb76..a248b3471b9 100644 --- a/vector/src/main/java/im/vector/app/features/login/terms/LocalizedFlowDataLoginTermsChecked.kt +++ b/vector/src/main/java/im/vector/app/features/login/terms/LocalizedFlowDataLoginTermsChecked.kt @@ -16,7 +16,7 @@ package im.vector.app.features.login.terms -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms data class LocalizedFlowDataLoginTermsChecked(val localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms, var checked: Boolean = false) diff --git a/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsFragment.kt b/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsFragment.kt index 43b148dcabd..262b79226ed 100755 --- a/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsFragment.kt @@ -31,7 +31,7 @@ import im.vector.app.features.login.AbstractLoginFragment import im.vector.app.features.login.LoginAction import im.vector.app.features.login.LoginViewState import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import javax.inject.Inject @Parcelize diff --git a/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsViewState.kt b/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsViewState.kt index 3641b443e3a..3a1dd19a09e 100644 --- a/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsViewState.kt +++ b/vector/src/main/java/im/vector/app/features/login/terms/LoginTermsViewState.kt @@ -17,7 +17,7 @@ package im.vector.app.features.login.terms import com.airbnb.mvrx.MavericksState -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms data class LoginTermsViewState( val localizedFlowDataLoginTermsChecked: List diff --git a/vector/src/main/java/im/vector/app/features/login/terms/PolicyController.kt b/vector/src/main/java/im/vector/app/features/login/terms/PolicyController.kt index 9f0086fb3ab..42c39efdacc 100644 --- a/vector/src/main/java/im/vector/app/features/login/terms/PolicyController.kt +++ b/vector/src/main/java/im/vector/app/features/login/terms/PolicyController.kt @@ -17,13 +17,14 @@ package im.vector.app.features.login.terms import com.airbnb.epoxy.TypedEpoxyController -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import javax.inject.Inject class PolicyController @Inject constructor() : TypedEpoxyController>() { var listener: PolicyControllerListener? = null + var horizontalPadding: Int? = null var homeServer: String? = null override fun buildModels(data: List) { @@ -32,6 +33,7 @@ class PolicyController @Inject constructor() : TypedEpoxyController() { @@ -38,6 +39,9 @@ abstract class PolicyItem : EpoxyModelWithHolder() { @EpoxyAttribute var subtitle: String? = null + @EpoxyAttribute + var horizontalPadding: Int? = null + @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var checkChangeListener: CompoundButton.OnCheckedChangeListener? = null @@ -46,13 +50,12 @@ abstract class PolicyItem : EpoxyModelWithHolder() { override fun bind(holder: Holder) { super.bind(holder) - holder.let { - it.checkbox.isChecked = checked - it.checkbox.setOnCheckedChangeListener(checkChangeListener) - it.title.text = title - it.subtitle.text = subtitle - it.view.onClick(clickListener) - } + horizontalPadding?.let { holder.view.setHorizontalPadding(it) } + holder.checkbox.isChecked = checked + holder.checkbox.setOnCheckedChangeListener(checkChangeListener) + holder.title.text = title + holder.subtitle.text = subtitle + holder.view.onClick(clickListener) } // Ensure checkbox behaves as expected (remove the listener) diff --git a/vector/src/main/java/im/vector/app/features/login/terms/converter.kt b/vector/src/main/java/im/vector/app/features/login/terms/converter.kt index f054a679bc6..64e4fb65d97 100644 --- a/vector/src/main/java/im/vector/app/features/login/terms/converter.kt +++ b/vector/src/main/java/im/vector/app/features/login/terms/converter.kt @@ -16,8 +16,8 @@ package im.vector.app.features.login.terms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import org.matrix.android.sdk.api.auth.registration.TermPolicies -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms /** * This method extract the policies from the login terms parameter, regarding the user language. @@ -48,15 +48,17 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String, val policies = get("policies") if (policies is Map<*, *>) { policies.keys.forEach { policyName -> - val localizedFlowDataLoginTerms = LocalizedFlowDataLoginTerms() - localizedFlowDataLoginTerms.policyName = policyName as String + val localizedFlowDataLoginTermsPolicyName = policyName as String + var localizedFlowDataLoginTermsVersion: String? = null + var localizedFlowDataLoginTermsLocalizedUrl: String? = null + var localizedFlowDataLoginTermsLocalizedName: String? = null val policy = policies[policyName] // Enter this policy if (policy is Map<*, *>) { // Version - localizedFlowDataLoginTerms.version = policy["version"] as String? + localizedFlowDataLoginTermsVersion = policy["version"] as String? var userLanguageUrlAndName: UrlAndName? = null var defaultLanguageUrlAndName: UrlAndName? = null @@ -86,21 +88,26 @@ fun TermPolicies.toLocalizedLoginTerms(userLanguage: String, // Copy found language data by priority when { userLanguageUrlAndName != null -> { - localizedFlowDataLoginTerms.localizedUrl = userLanguageUrlAndName!!.url - localizedFlowDataLoginTerms.localizedName = userLanguageUrlAndName!!.name + localizedFlowDataLoginTermsLocalizedUrl = userLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = userLanguageUrlAndName!!.name } defaultLanguageUrlAndName != null -> { - localizedFlowDataLoginTerms.localizedUrl = defaultLanguageUrlAndName!!.url - localizedFlowDataLoginTerms.localizedName = defaultLanguageUrlAndName!!.name + localizedFlowDataLoginTermsLocalizedUrl = defaultLanguageUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = defaultLanguageUrlAndName!!.name } firstUrlAndName != null -> { - localizedFlowDataLoginTerms.localizedUrl = firstUrlAndName!!.url - localizedFlowDataLoginTerms.localizedName = firstUrlAndName!!.name + localizedFlowDataLoginTermsLocalizedUrl = firstUrlAndName!!.url + localizedFlowDataLoginTermsLocalizedName = firstUrlAndName!!.name } } } - result.add(localizedFlowDataLoginTerms) + result.add(LocalizedFlowDataLoginTerms( + policyName = localizedFlowDataLoginTermsPolicyName, + version = localizedFlowDataLoginTermsVersion, + localizedUrl = localizedFlowDataLoginTermsLocalizedUrl, + localizedName = localizedFlowDataLoginTermsLocalizedName + )) } } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt index 62179fbc32f..85e2e0cea33 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginAction2.kt @@ -21,7 +21,7 @@ import im.vector.app.features.login.LoginConfig import org.matrix.android.sdk.api.auth.data.Credentials import org.matrix.android.sdk.api.auth.data.SsoIdentityProvider import org.matrix.android.sdk.api.auth.registration.RegisterThreePid -import org.matrix.android.sdk.internal.network.ssl.Fingerprint +import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed class LoginAction2 : VectorViewModelAction { // First action diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt index 222949bcbdc..f729584f51f 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginCaptchaFragment2.kt @@ -37,7 +37,7 @@ import im.vector.app.core.utils.AssetReader import im.vector.app.databinding.FragmentLoginCaptchaBinding import im.vector.app.features.login.JavascriptResponse import im.vector.app.features.login.LoginCaptchaFragmentArgument -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder import java.util.Formatter @@ -166,7 +166,7 @@ class LoginCaptchaFragment2 @Inject constructor( try { // URL decode json = URLDecoder.decode(json, "UTF-8") - javascriptResponse = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java).fromJson(json) + javascriptResponse = MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java).fromJson(json) } catch (e: Exception) { Timber.e(e, "## shouldOverrideUrlLoading(): failed") } diff --git a/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt index 4427f08309e..789cd459ac9 100644 --- a/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/LoginWebFragment2.kt @@ -39,7 +39,7 @@ import im.vector.app.features.login.JavascriptResponse import im.vector.app.features.signout.soft.SoftLogoutAction import im.vector.app.features.signout.soft.SoftLogoutViewModel import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder import javax.inject.Inject @@ -204,7 +204,7 @@ class LoginWebFragment2 @Inject constructor( try { // URL decode json = URLDecoder.decode(json, "UTF-8") - val adapter = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java) + val adapter = MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java) javascriptResponse = adapter.fromJson(json) } catch (e: Exception) { Timber.e(e, "## shouldOverrideUrlLoading() : fromJson failed") diff --git a/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt b/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt index 0be696e1c8d..303fc5ef177 100755 --- a/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt +++ b/vector/src/main/java/im/vector/app/features/login2/terms/LoginTermsFragment2.kt @@ -33,7 +33,7 @@ import im.vector.app.features.login.terms.PolicyController import im.vector.app.features.login2.AbstractLoginFragment2 import im.vector.app.features.login2.LoginAction2 import im.vector.app.features.login2.LoginViewState2 -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import javax.inject.Inject /** diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToAction.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToAction.kt index f38049640d3..25db8116003 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToAction.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToAction.kt @@ -24,7 +24,7 @@ sealed class MatrixToAction : VectorViewModelAction { object FailedToResolveUser : MatrixToAction() object FailedToStartChatting : MatrixToAction() data class JoinSpace(val spaceID: String, val viaServers: List?) : MatrixToAction() - data class JoinRoom(val roomId: String, val viaServers: List?) : MatrixToAction() + data class JoinRoom(val roomIdOrAlias: String, val viaServers: List?) : MatrixToAction() data class OpenSpace(val spaceID: String) : MatrixToAction() data class OpenRoom(val roomId: String) : MatrixToAction() } diff --git a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt index 04c2c8dd44f..6d0e380bc9d 100644 --- a/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/matrixto/MatrixToBottomSheetViewModel.kt @@ -33,6 +33,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.features.createdirect.DirectRoomHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.permalinks.PermalinkData @@ -296,8 +297,12 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( } viewModelScope.launch { try { - session.joinRoom(action.roomId, null, action.viaServers?.take(3) ?: emptyList()) - _viewEvents.post(MatrixToViewEvents.NavigateToRoom(action.roomId)) + session.joinRoom( + roomIdOrAlias = action.roomIdOrAlias, + reason = null, + viaServers = action.viaServers?.take(3) ?: emptyList() + ) + _viewEvents.post(MatrixToViewEvents.NavigateToRoom(getRoomIdFromRoomIdOrAlias(action.roomIdOrAlias))) } catch (failure: Throwable) { _viewEvents.post(MatrixToViewEvents.ShowModalError(errorFormatter.toHumanReadable(failure))) } finally { @@ -309,6 +314,12 @@ class MatrixToBottomSheetViewModel @AssistedInject constructor( } } + private suspend fun getRoomIdFromRoomIdOrAlias(roomIdOrAlias: String): String { + return if (MatrixPatterns.isRoomAlias(roomIdOrAlias)) { + session.getRoomIdByAlias(roomIdOrAlias, true).get().roomId + } else roomIdOrAlias + } + private fun handleStartChatting(action: MatrixToAction.StartChattingWithUser) { setState { copy(startChattingState = Loading()) diff --git a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt index 65c99362b9d..50325327db5 100644 --- a/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/ImageContentRenderer.kt @@ -44,8 +44,8 @@ import im.vector.app.core.utils.DimensionConverter import kotlinx.parcelize.Parcelize import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.content.ContentUrlResolver +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt import org.matrix.android.sdk.api.session.media.PreviewUrlData -import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt import timber.log.Timber import java.io.File import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt index 781a176550e..cd868c9f2f4 100644 --- a/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt +++ b/vector/src/main/java/im/vector/app/features/media/RoomEventsAttachmentProvider.kt @@ -21,6 +21,7 @@ import im.vector.app.core.resources.StringProvider import im.vector.lib.attachmentviewer.AttachmentInfo import kotlinx.coroutines.CoroutineScope import org.matrix.android.sdk.api.extensions.tryOrNull +import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.file.FileService import org.matrix.android.sdk.api.session.room.model.message.MessageContent @@ -32,7 +33,6 @@ import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.util.MimeTypes -import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt import java.io.File class RoomEventsAttachmentProvider( diff --git a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt index 635de2ba169..4e6d19686b9 100644 --- a/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt +++ b/vector/src/main/java/im/vector/app/features/media/VideoContentRenderer.kt @@ -31,7 +31,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt +import org.matrix.android.sdk.api.session.crypto.attachments.ElementToDecrypt import timber.log.Timber import java.net.URLEncoder import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt index 8ff70c29540..6122cf1eee9 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/DefaultNavigator.kt @@ -176,6 +176,9 @@ class DefaultNavigator @Inject constructor( Navigator.PostSwitchSpaceAction.OpenAddExistingRooms -> { startActivity(context, SpaceManageActivity.newIntent(context, spaceId, ManageType.AddRooms), false) } + Navigator.PostSwitchSpaceAction.OpenRoomList -> { + startActivity(context, SpaceExploreActivity.newIntent(context, spaceId), buildTask = false) + } is Navigator.PostSwitchSpaceAction.OpenDefaultRoom -> { val args = TimelineArgs( postSwitchSpaceAction.roomId, diff --git a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt index 85826fad5ba..310105bd955 100644 --- a/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt +++ b/vector/src/main/java/im/vector/app/features/navigation/Navigator.kt @@ -54,8 +54,9 @@ interface Navigator { sealed class PostSwitchSpaceAction { object None : PostSwitchSpaceAction() - data class OpenDefaultRoom(val roomId: String, val showShareSheet: Boolean) : PostSwitchSpaceAction() object OpenAddExistingRooms : PostSwitchSpaceAction() + object OpenRoomList : PostSwitchSpaceAction() + data class OpenDefaultRoom(val roomId: String, val showShareSheet: Boolean) : PostSwitchSpaceAction() } fun switchToSpace(context: Context, spaceId: String, postSwitchSpaceAction: PostSwitchSpaceAction) diff --git a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt index 3c9b985df5d..855774e5128 100644 --- a/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt +++ b/vector/src/main/java/im/vector/app/features/notifications/NotifiableEventResolver.kt @@ -27,6 +27,7 @@ import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.content.ContentUrlResolver import org.matrix.android.sdk.api.session.crypto.MXCryptoError +import org.matrix.android.sdk.api.session.crypto.model.OlmDecryptionResult import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.isEdition @@ -41,7 +42,6 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.getEditedEventId import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent import org.matrix.android.sdk.api.util.toMatrixItem -import org.matrix.android.sdk.internal.crypto.algorithms.olm.OlmDecryptionResult import timber.log.Timber import java.util.UUID import javax.inject.Inject @@ -155,7 +155,8 @@ class NotifiableEventResolver @Inject constructor( // only convert encrypted messages to NotifiableMessageEvents when (event.root.getClearType()) { EventType.MESSAGE, - in EventType.POLL_START -> { + in EventType.POLL_START, + in EventType.STATE_ROOM_BEACON_INFO -> { val body = displayableEventFormatter.format(event, isDm = room.roomSummary()?.isDirect.orFalse(), appendAuthor = false).toString() val roomName = room.roomSummary()?.displayName ?: "" val senderDisplayName = event.senderInfo.disambiguatedDisplayName @@ -187,7 +188,7 @@ class NotifiableEventResolver @Inject constructor( soundName = null ) } - else -> null + else -> null } } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt b/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt index 7ef4dfb6099..171d8f7bb53 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/DirectLoginUseCase.kt @@ -17,6 +17,7 @@ package im.vector.app.features.onboarding import im.vector.app.R +import im.vector.app.core.extensions.andThen import im.vector.app.core.resources.StringProvider import im.vector.app.features.onboarding.OnboardingAction.LoginOrRegister import org.matrix.android.sdk.api.MatrixPatterns.getDomain @@ -24,7 +25,6 @@ import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig import org.matrix.android.sdk.api.auth.wellknown.WellknownResult import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.internal.extensions.andThen import javax.inject.Inject class DirectLoginUseCase @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt index 7510f235842..9f7dce56ead 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingAction.kt @@ -22,14 +22,21 @@ import im.vector.app.features.login.LoginConfig import im.vector.app.features.login.ServerType import im.vector.app.features.login.SignMode import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.network.ssl.Fingerprint +import org.matrix.android.sdk.api.network.ssl.Fingerprint sealed interface OnboardingAction : VectorViewModelAction { data class OnGetStarted(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction data class OnIAlreadyHaveAnAccount(val resetLoginConfig: Boolean, val onboardingFlow: OnboardingFlow) : OnboardingAction data class UpdateServerType(val serverType: ServerType) : OnboardingAction - data class UpdateHomeServer(val homeServerUrl: String) : OnboardingAction + + sealed interface HomeServerChange : OnboardingAction { + val homeServerUrl: String + + data class SelectHomeServer(override val homeServerUrl: String) : HomeServerChange + data class EditHomeServer(override val homeServerUrl: String) : HomeServerChange + } + data class UpdateUseCase(val useCase: FtueUseCase) : OnboardingAction object ResetUseCase : OnboardingAction data class UpdateSignMode(val signMode: SignMode) : OnboardingAction diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt index 853b0c330e8..ee406aff48b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewEvents.kt @@ -37,8 +37,10 @@ sealed class OnboardingViewEvents : VectorViewEvents { object OpenUseCaseSelection : OnboardingViewEvents() object OpenServerSelection : OnboardingViewEvents() object OpenCombinedRegister : OnboardingViewEvents() + object EditServerSelection : OnboardingViewEvents() data class OnServerSelectionDone(val serverType: ServerType) : OnboardingViewEvents() object OnLoginFlowRetrieved : OnboardingViewEvents() + object OnHomeserverEdited : OnboardingViewEvents() data class OnSignModeSelected(val signMode: SignMode) : OnboardingViewEvents() object OnForgetPasswordClicked : OnboardingViewEvents() object OnResetPasswordSendThreePidDone : OnboardingViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt index dbd257464eb..2b286e6d931 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewModel.kt @@ -41,13 +41,13 @@ import im.vector.app.features.login.LoginMode import im.vector.app.features.login.ReAuthHelper import im.vector.app.features.login.ServerType import im.vector.app.features.login.SignMode +import im.vector.app.features.onboarding.StartAuthenticationFlowUseCase.StartAuthenticationResult import kotlinx.coroutines.Job import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.HomeServerHistoryService import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig -import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.login.LoginWizard import org.matrix.android.sdk.api.auth.registration.FlowResult import org.matrix.android.sdk.api.auth.registration.RegistrationResult @@ -75,6 +75,7 @@ class OnboardingViewModel @AssistedInject constructor( private val uriFilenameResolver: UriFilenameResolver, private val registrationActionHandler: RegistrationActionHandler, private val directLoginUseCase: DirectLoginUseCase, + private val startAuthenticationFlowUseCase: StartAuthenticationFlowUseCase, private val vectorOverrides: VectorOverrides ) : VectorViewModel(initialState) { @@ -107,6 +108,7 @@ class OnboardingViewModel @AssistedInject constructor( private var currentHomeServerConnectionConfig: HomeServerConnectionConfig? = null private val matrixOrgUrl = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() + private val defaultHomeserverUrl = matrixOrgUrl private val registrationWizard: RegistrationWizard get() = authenticationService.getRegistrationWizard() @@ -139,14 +141,14 @@ class OnboardingViewModel @AssistedInject constructor( is OnboardingAction.UpdateServerType -> handleUpdateServerType(action) is OnboardingAction.UpdateSignMode -> handleUpdateSignMode(action) is OnboardingAction.InitWith -> handleInitWith(action) - is OnboardingAction.UpdateHomeServer -> handleUpdateHomeserver(action).also { lastAction = action } + is OnboardingAction.HomeServerChange -> withAction(action) { handleHomeserverChange(action) } is OnboardingAction.LoginOrRegister -> handleLoginOrRegister(action).also { lastAction = action } is OnboardingAction.Register -> handleRegisterWith(action).also { lastAction = action } is OnboardingAction.LoginWithToken -> handleLoginWithToken(action) is OnboardingAction.WebLoginSuccess -> handleWebLoginSuccess(action) is OnboardingAction.ResetPassword -> handleResetPassword(action) is OnboardingAction.ResetPasswordMailConfirmed -> handleResetPasswordMailConfirmed() - is OnboardingAction.PostRegisterAction -> handleRegisterAction(action.registerAction) + is OnboardingAction.PostRegisterAction -> handleRegisterAction(action.registerAction, ::emitFlowResultViewEvent) is OnboardingAction.ResetAction -> handleResetAction(action) is OnboardingAction.UserAcceptCertificate -> handleUserAcceptCertificate(action) OnboardingAction.ClearHomeServerHistory -> handleClearHomeServerHistory() @@ -161,25 +163,30 @@ class OnboardingViewModel @AssistedInject constructor( } } + private fun withAction(action: OnboardingAction, block: (OnboardingAction) -> Unit) { + lastAction = action + block(action) + } + private fun handleSplashAction(resetConfig: Boolean, onboardingFlow: OnboardingFlow) { if (resetConfig) { loginConfig = null } setState { copy(onboardingFlow = onboardingFlow) } - val configUrl = loginConfig?.homeServerUrl?.takeIf { it.isNotEmpty() } - if (configUrl != null) { - // Use config from uri - val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(configUrl) - if (homeServerConnectionConfig == null) { - // Url is invalid, in this case, just use the regular flow - Timber.w("Url from config url was invalid: $configUrl") - continueToPageAfterSplash(onboardingFlow) - } else { - getLoginFlow(homeServerConnectionConfig, ServerType.Other) + return when (val config = loginConfig.toHomeserverConfig()) { + null -> continueToPageAfterSplash(onboardingFlow) + else -> startAuthenticationFlow(trigger = null, config, ServerType.Other) + } + } + + private fun LoginConfig?.toHomeserverConfig(): HomeServerConnectionConfig? { + return this?.homeServerUrl?.takeIf { it.isNotEmpty() }?.let { url -> + homeServerConnectionConfigFactory.create(url).also { + if (it == null) { + Timber.w("Url from config url was invalid: $url") + } } - } else { - continueToPageAfterSplash(onboardingFlow) } } @@ -200,12 +207,12 @@ class OnboardingViewModel @AssistedInject constructor( // It happens when we get the login flow, or during direct authentication. // So alter the homeserver config and retrieve again the login flow when (val finalLastAction = lastAction) { - is OnboardingAction.UpdateHomeServer -> { + is OnboardingAction.HomeServerChange.SelectHomeServer -> { currentHomeServerConnectionConfig ?.let { it.copy(allowedFingerprints = it.allowedFingerprints + action.fingerprint) } - ?.let { getLoginFlow(it) } + ?.let { startAuthenticationFlow(finalLastAction, it) } } - is OnboardingAction.LoginOrRegister -> + is OnboardingAction.LoginOrRegister -> handleDirectLogin( finalLastAction, HomeServerConnectionConfig.Builder() @@ -214,7 +221,7 @@ class OnboardingViewModel @AssistedInject constructor( .withAllowedFingerPrints(listOf(action.fingerprint)) .build() ) - else -> Unit + else -> Unit } } @@ -249,41 +256,52 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleRegisterAction(action: RegisterAction) { + private fun handleRegisterAction(action: RegisterAction, onNextRegistrationStepAction: (FlowResult) -> Unit) { currentJob = viewModelScope.launch { if (action.hasLoadingState()) { setState { copy(isLoading = true) } } - runCatching { registrationActionHandler.handleRegisterAction(registrationWizard, action) } - .fold( - onSuccess = { - when { - action.ignoresResult() -> { - // do nothing - } - else -> when (it) { - is RegistrationResult.Success -> onSessionCreated(it.session, isAccountCreated = true) - is RegistrationResult.FlowResponse -> onFlowResponse(it.flowResult) - } + internalRegisterAction(action, onNextRegistrationStepAction) + setState { copy(isLoading = false) } + } + } + + private suspend fun internalRegisterAction(action: RegisterAction, onNextRegistrationStepAction: (FlowResult) -> Unit) { + runCatching { registrationActionHandler.handleRegisterAction(registrationWizard, action) } + .fold( + onSuccess = { + when { + action.ignoresResult() -> { + // do nothing } - }, - onFailure = { - if (it !is CancellationException) { - _viewEvents.post(OnboardingViewEvents.Failure(it)) + else -> when (it) { + is RegistrationResult.Success -> onSessionCreated(it.session, isAccountCreated = true) + is RegistrationResult.FlowResponse -> onFlowResponse(it.flowResult, onNextRegistrationStepAction) } } - ) - setState { copy(isLoading = false) } - } + }, + onFailure = { + if (it !is CancellationException) { + _viewEvents.post(OnboardingViewEvents.Failure(it)) + } + } + ) + } + + private fun emitFlowResultViewEvent(flowResult: FlowResult) { + _viewEvents.post(OnboardingViewEvents.RegistrationFlowResult(flowResult, isRegistrationStarted)) } private fun handleRegisterWith(action: OnboardingAction.Register) { reAuthHelper.data = action.password - handleRegisterAction(RegisterAction.CreateAccount( - action.username, - action.password, - action.initialDeviceName - )) + handleRegisterAction( + RegisterAction.CreateAccount( + action.username, + action.password, + action.initialDeviceName + ), + ::emitFlowResultViewEvent + ) } private fun handleResetAction(action: OnboardingAction.ResetAction) { @@ -291,24 +309,16 @@ class OnboardingViewModel @AssistedInject constructor( currentJob = null when (action) { - OnboardingAction.ResetHomeServerType -> { - setState { - copy( - serverType = ServerType.Unknown - ) - } + OnboardingAction.ResetHomeServerType -> { + setState { copy(serverType = ServerType.Unknown) } } - OnboardingAction.ResetHomeServerUrl -> { + OnboardingAction.ResetHomeServerUrl -> { viewModelScope.launch { authenticationService.reset() setState { copy( isLoading = false, - homeServerUrlFromUser = null, - homeServerUrl = null, - loginMode = LoginMode.Unknown, - serverType = ServerType.Unknown, - loginModeSupportedTypes = emptyList() + selectedHomeserver = SelectedHomeserverState(), ) } } @@ -318,8 +328,6 @@ class OnboardingViewModel @AssistedInject constructor( copy( isLoading = false, signMode = SignMode.Unknown, - loginMode = LoginMode.Unknown, - loginModeSupportedTypes = emptyList() ) } } @@ -341,27 +349,23 @@ class OnboardingViewModel @AssistedInject constructor( } private fun handleUpdateSignMode(action: OnboardingAction.UpdateSignMode) { - setState { - copy( - signMode = action.signMode - ) - } - + updateSignMode(action.signMode) when (action.signMode) { - SignMode.SignUp -> handleRegisterAction(RegisterAction.StartRegistration) + SignMode.SignUp -> handleRegisterAction(RegisterAction.StartRegistration, ::emitFlowResultViewEvent) SignMode.SignIn -> startAuthenticationFlow() SignMode.SignInWithMatrixId -> _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.SignInWithMatrixId)) SignMode.Unknown -> Unit } } + private fun updateSignMode(signMode: SignMode) { + setState { copy(signMode = signMode) } + } + private fun handleUpdateUseCase(action: OnboardingAction.UpdateUseCase) { setState { copy(useCase = action.useCase) } when (vectorFeatures.isOnboardingCombinedRegisterEnabled()) { - true -> { - handle(OnboardingAction.UpdateHomeServer(matrixOrgUrl)) - OnboardingViewEvents.OpenCombinedRegister - } + true -> handle(OnboardingAction.HomeServerChange.SelectHomeServer(defaultHomeserverUrl)) false -> _viewEvents.post(OnboardingViewEvents.OpenServerSelection) } } @@ -381,7 +385,7 @@ class OnboardingViewModel @AssistedInject constructor( ServerType.Unknown -> Unit /* Should not happen */ ServerType.MatrixOrg -> // Request login flow here - handle(OnboardingAction.UpdateHomeServer(matrixOrgUrl)) + handle(OnboardingAction.HomeServerChange.SelectHomeServer(matrixOrgUrl)) ServerType.EMS, ServerType.Other -> _viewEvents.post(OnboardingViewEvents.OnServerSelectionDone(action.serverType)) } @@ -516,18 +520,17 @@ class OnboardingViewModel @AssistedInject constructor( _viewEvents.post(OnboardingViewEvents.OnSignModeSelected(SignMode.SignIn)) } - private fun onFlowResponse(flowResult: FlowResult) { + private suspend fun onFlowResponse(flowResult: FlowResult, onNextRegistrationStepAction: (FlowResult) -> Unit) { // If dummy stage is mandatory, and password is already sent, do the dummy stage now if (isRegistrationStarted && flowResult.missingStages.any { it is Stage.Dummy && it.mandatory }) { - handleRegisterDummy() + handleRegisterDummy(onNextRegistrationStepAction) } else { - // Notify the user - _viewEvents.post(OnboardingViewEvents.RegistrationFlowResult(flowResult, isRegistrationStarted)) + onNextRegistrationStepAction(flowResult) } } - private fun handleRegisterDummy() { - handleRegisterAction(RegisterAction.RegisterDummy) + private suspend fun handleRegisterDummy(onNextRegistrationStepAction: (FlowResult) -> Unit) { + internalRegisterAction(RegisterAction.RegisterDummy, onNextRegistrationStepAction) } private suspend fun onSessionCreated(session: Session, isAccountCreated: Boolean) { @@ -571,7 +574,7 @@ class OnboardingViewModel @AssistedInject constructor( } private fun handleWebLoginSuccess(action: OnboardingAction.WebLoginSuccess) = withState { state -> - val homeServerConnectionConfigFinal = homeServerConnectionConfigFactory.create(state.homeServerUrl) + val homeServerConnectionConfigFinal = homeServerConnectionConfigFactory.create(state.selectedHomeserver.upstreamUrl) if (homeServerConnectionConfigFinal == null) { // Should not happen @@ -588,85 +591,66 @@ class OnboardingViewModel @AssistedInject constructor( } } - private fun handleUpdateHomeserver(action: OnboardingAction.UpdateHomeServer) { + private fun handleHomeserverChange(action: OnboardingAction.HomeServerChange) { val homeServerConnectionConfig = homeServerConnectionConfigFactory.create(action.homeServerUrl) if (homeServerConnectionConfig == null) { // This is invalid _viewEvents.post(OnboardingViewEvents.Failure(Throwable("Unable to create a HomeServerConnectionConfig"))) } else { - getLoginFlow(homeServerConnectionConfig) + startAuthenticationFlow(action, homeServerConnectionConfig) } } - private fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, - serverTypeOverride: ServerType? = null) { + private fun startAuthenticationFlow( + trigger: OnboardingAction?, + homeServerConnectionConfig: HomeServerConnectionConfig, + serverTypeOverride: ServerType? = null + ) { currentHomeServerConnectionConfig = homeServerConnectionConfig currentJob = viewModelScope.launch { - authenticationService.cancelPendingLoginOrRegistration() - - setState { - copy( - isLoading = true, - // If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg - // It is also useful to set the value again in the case of a certificate error on matrix.org - serverType = if (homeServerConnectionConfig.homeServerUri.toString() == matrixOrgUrl) { - ServerType.MatrixOrg - } else { - serverTypeOverride ?: serverType - } - ) - } - - val data = try { - authenticationService.getLoginFlow(homeServerConnectionConfig) - } catch (failure: Throwable) { - setState { - copy( - isLoading = false, - // If we were trying to retrieve matrix.org login flow, also reset the serverType - serverType = if (serverType == ServerType.MatrixOrg) ServerType.Unknown else serverType - ) - } - _viewEvents.post(OnboardingViewEvents.Failure(failure)) - null - } - - data ?: return@launch - - // Valid Homeserver, add it to the history. - // Note: we add what the user has input, data.homeServerUrlBase can be different - rememberHomeServer(homeServerConnectionConfig.homeServerUri.toString()) + setState { copy(isLoading = true) } + runCatching { startAuthenticationFlowUseCase.execute(homeServerConnectionConfig) }.fold( + onSuccess = { onAuthenticationStartedSuccess(trigger, homeServerConnectionConfig, it, serverTypeOverride) }, + onFailure = { _viewEvents.post(OnboardingViewEvents.Failure(it)) } + ) + setState { copy(isLoading = false) } + } + } - val loginMode = when { - // SSO login is taken first - data.supportedLoginTypes.contains(LoginFlowTypes.SSO) && - data.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(data.ssoIdentityProviders) - data.supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(data.ssoIdentityProviders) - data.supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password - else -> LoginMode.Unsupported - } + private suspend fun onAuthenticationStartedSuccess( + trigger: OnboardingAction?, + config: HomeServerConnectionConfig, + authResult: StartAuthenticationResult, + serverTypeOverride: ServerType? + ) { + rememberHomeServer(config.homeServerUri.toString()) + if (authResult.isHomeserverOutdated) { + _viewEvents.post(OnboardingViewEvents.OutdatedHomeserver) + } - setState { - copy( - isLoading = false, - homeServerUrlFromUser = homeServerConnectionConfig.homeServerUri.toString(), - homeServerUrl = data.homeServerUrl, - loginMode = loginMode, - loginModeSupportedTypes = data.supportedLoginTypes.toList() - ) - } - if ((loginMode == LoginMode.Password && !data.isLoginAndRegistrationSupported) || - data.isOutdatedHomeserver) { - // Notify the UI - _viewEvents.post(OnboardingViewEvents.OutdatedHomeserver) + when (trigger) { + is OnboardingAction.HomeServerChange.EditHomeServer -> { + when (awaitState().onboardingFlow) { + OnboardingFlow.SignUp -> internalRegisterAction(RegisterAction.StartRegistration) { _ -> + updateServerSelection(config, serverTypeOverride, authResult) + _viewEvents.post(OnboardingViewEvents.OnHomeserverEdited) + } + else -> throw IllegalArgumentException("developer error") + } } - - withState { - if (loginMode.supportsSignModeScreen()) { - when (it.onboardingFlow) { - OnboardingFlow.SignIn -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignIn)) - OnboardingFlow.SignUp -> handleUpdateSignMode(OnboardingAction.UpdateSignMode(SignMode.SignUp)) + is OnboardingAction.HomeServerChange.SelectHomeServer -> { + updateServerSelection(config, serverTypeOverride, authResult) + if (authResult.selectedHomeserver.preferredLoginMode.supportsSignModeScreen()) { + when (awaitState().onboardingFlow) { + OnboardingFlow.SignIn -> { + updateSignMode(SignMode.SignIn) + internalRegisterAction(RegisterAction.StartRegistration, ::emitFlowResultViewEvent) + } + OnboardingFlow.SignUp -> { + updateSignMode(SignMode.SignUp) + internalRegisterAction(RegisterAction.StartRegistration, ::emitFlowResultViewEvent) + } OnboardingFlow.SignInSignUp, null -> { _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) @@ -676,6 +660,31 @@ class OnboardingViewModel @AssistedInject constructor( _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) } } + else -> { + updateServerSelection(config, serverTypeOverride, authResult) + _viewEvents.post(OnboardingViewEvents.OnLoginFlowRetrieved) + } + } + } + + private fun updateServerSelection(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?, authResult: StartAuthenticationResult) { + setState { + copy( + serverType = alignServerTypeAfterSubmission(config, serverTypeOverride), + selectedHomeserver = authResult.selectedHomeserver, + ) + } + } + + /** + * If user has entered https://matrix.org, ensure that server type is ServerType.MatrixOrg + * It is also useful to set the value again in the case of a certificate error on matrix.org + **/ + private fun OnboardingViewState.alignServerTypeAfterSubmission(config: HomeServerConnectionConfig, serverTypeOverride: ServerType?): ServerType { + return if (config.homeServerUri.toString() == matrixOrgUrl) { + ServerType.MatrixOrg + } else { + serverTypeOverride ?: serverType } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt index b98e8116798..442a0a7df17 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/OnboardingViewState.kt @@ -40,26 +40,17 @@ data class OnboardingViewState( val signMode: SignMode = SignMode.Unknown, @PersistState val resetPasswordEmail: String? = null, - @PersistState - val homeServerUrlFromUser: String? = null, - - // Can be modified after a Wellknown request - @PersistState - val homeServerUrl: String? = null, // For SSO session recovery @PersistState val deviceId: String? = null, - // Network result - @PersistState - val loginMode: LoginMode = LoginMode.Unknown, - // Supported types for the login. We cannot use a sealed class for LoginType because it is not serializable - @PersistState - val loginModeSupportedTypes: List = emptyList(), val knownCustomHomeServersUrls: List = emptyList(), val isForceLoginFallbackEnabled: Boolean = false, + @PersistState + val selectedHomeserver: SelectedHomeserverState = SelectedHomeserverState(), + @PersistState val personalizationState: PersonalizationState = PersonalizationState() ) : MavericksState @@ -70,6 +61,15 @@ enum class OnboardingFlow { SignInSignUp } +@Parcelize +data class SelectedHomeserverState( + val description: String? = null, + val userFacingUrl: String? = null, + val upstreamUrl: String? = null, + val preferredLoginMode: LoginMode = LoginMode.Unknown, + val supportedLoginTypes: List = emptyList(), +) : Parcelable + @Parcelize data class PersonalizationState( val supportsChangingDisplayName: Boolean = false, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt b/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt new file mode 100644 index 00000000000..53e1c47fa19 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/StartAuthenticationFlowUseCase.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding + +import im.vector.app.R +import im.vector.app.core.extensions.containsAllItems +import im.vector.app.core.resources.StringProvider +import im.vector.app.core.utils.ensureTrailingSlash +import im.vector.app.features.login.LoginMode +import org.matrix.android.sdk.api.auth.AuthenticationService +import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig +import org.matrix.android.sdk.api.auth.data.LoginFlowResult +import org.matrix.android.sdk.api.auth.data.LoginFlowTypes +import javax.inject.Inject + +class StartAuthenticationFlowUseCase @Inject constructor( + private val authenticationService: AuthenticationService, + private val stringProvider: StringProvider +) { + + suspend fun execute(config: HomeServerConnectionConfig): StartAuthenticationResult { + authenticationService.cancelPendingLoginOrRegistration() + val authFlow = authenticationService.getLoginFlow(config) + val preferredLoginMode = authFlow.findPreferredLoginMode() + val selection = createSelectedHomeserver(authFlow, config, preferredLoginMode) + val isOutdated = (preferredLoginMode == LoginMode.Password && !authFlow.isLoginAndRegistrationSupported) || authFlow.isOutdatedHomeserver + return StartAuthenticationResult(isOutdated, selection) + } + + private fun createSelectedHomeserver( + authFlow: LoginFlowResult, + config: HomeServerConnectionConfig, + preferredLoginMode: LoginMode + ) = SelectedHomeserverState( + description = when (config.homeServerUri.toString()) { + matrixOrgUrl() -> stringProvider.getString(R.string.ftue_auth_create_account_matrix_dot_org_server_description) + else -> null + }, + userFacingUrl = config.homeServerUri.toString(), + upstreamUrl = authFlow.homeServerUrl, + preferredLoginMode = preferredLoginMode, + supportedLoginTypes = authFlow.supportedLoginTypes + ) + + private fun matrixOrgUrl() = stringProvider.getString(R.string.matrix_org_server_url).ensureTrailingSlash() + + private fun LoginFlowResult.findPreferredLoginMode() = when { + supportedLoginTypes.containsAllItems(LoginFlowTypes.SSO, LoginFlowTypes.PASSWORD) -> LoginMode.SsoAndPassword(ssoIdentityProviders) + supportedLoginTypes.contains(LoginFlowTypes.SSO) -> LoginMode.Sso(ssoIdentityProviders) + supportedLoginTypes.contains(LoginFlowTypes.PASSWORD) -> LoginMode.Password + else -> LoginMode.Unsupported + } + + data class StartAuthenticationResult( + val isHomeserverOutdated: Boolean, + val selectedHomeserver: SelectedHomeserverState + ) +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt index 2e9925516cd..a032181e4d9 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/AbstractSSOFtueAuthFragment.kt @@ -37,7 +37,7 @@ abstract class AbstractSSOFtueAuthFragment : AbstractFtueAuthF override fun onStart() { super.onStart() - val hasSSO = withState(viewModel) { it.loginMode.hasSso() } + val hasSSO = withState(viewModel) { it.selectedHomeserver.preferredLoginMode.hasSso() } if (hasSSO) { val packageName = CustomTabsClient.getPackageName(requireContext(), null) @@ -67,7 +67,7 @@ abstract class AbstractSSOFtueAuthFragment : AbstractFtueAuthF override fun onStop() { super.onStop() - val hasSSO = withState(viewModel) { it.loginMode.hasSso() } + val hasSSO = withState(viewModel) { it.selectedHomeserver.preferredLoginMode.hasSso() } if (hasSSO) { customTabsServiceConnection?.let { requireContext().unbindService(it) } customTabsServiceConnection = null @@ -88,7 +88,7 @@ abstract class AbstractSSOFtueAuthFragment : AbstractFtueAuthF private fun prefetchIfNeeded() { withState(viewModel) { state -> - if (state.loginMode.hasSso() && state.loginMode.ssoIdentityProviders().isNullOrEmpty()) { + if (state.selectedHomeserver.preferredLoginMode.hasSso() && state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders().isNullOrEmpty()) { // in this case we can prefetch (not other cases for privacy concerns) viewModel.getSsoUrl( redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL, diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt new file mode 100644 index 00000000000..558c26fe56b --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/CaptchaWebview.kt @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import android.annotation.SuppressLint +import android.content.DialogInterface +import android.graphics.Bitmap +import android.net.http.SslError +import android.os.Build +import android.view.KeyEvent +import android.view.View +import android.webkit.SslErrorHandler +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import androidx.core.view.isVisible +import androidx.fragment.app.Fragment +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import im.vector.app.R +import im.vector.app.core.utils.AssetReader +import im.vector.app.features.login.JavascriptResponse +import im.vector.app.features.onboarding.OnboardingViewState +import org.matrix.android.sdk.api.util.MatrixJsonParser +import timber.log.Timber +import java.net.URLDecoder +import java.util.Formatter +import javax.inject.Inject + +class CaptchaWebview @Inject constructor( + private val assetReader: AssetReader +) { + + @SuppressLint("SetJavaScriptEnabled") + fun setupWebView( + container: Fragment, + webView: WebView, + progressView: View, + siteKey: String, + state: OnboardingViewState, + onSuccess: (String) -> Unit + ) { + webView.settings.javaScriptEnabled = true + + val reCaptchaPage = assetReader.readAssetFile("reCaptchaPage.html") ?: error("missing asset reCaptchaPage.html") + + val html = Formatter().format(reCaptchaPage, siteKey).toString() + val mime = "text/html" + val encoding = "utf-8" + + val homeServerUrl = state.selectedHomeserver.upstreamUrl ?: error("missing url of homeserver") + webView.loadDataWithBaseURL(homeServerUrl, html, mime, encoding, null) + webView.requestLayout() + + webView.webViewClient = object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + if (container.isAdded) { + progressView.isVisible = true + } + } + + override fun onPageFinished(view: WebView, url: String) { + super.onPageFinished(view, url) + if (container.isAdded) { + progressView.isVisible = false + } + } + + override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) { + Timber.d("## onReceivedSslError() : ${error.certificate}") + if (container.isAdded) { + showSslErrorDialog(container, handler) + } + } + + private fun onError(errorMessage: String) { + Timber.e("## onError() : $errorMessage") + } + + @SuppressLint("NewApi") + override fun onReceivedHttpError(view: WebView, request: WebResourceRequest, errorResponse: WebResourceResponse) { + super.onReceivedHttpError(view, request, errorResponse) + when { + request.url.toString().endsWith("favicon.ico") -> { + // ignore favicon errors + } + else -> onError(errorResponse.toText()) + } + } + + override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) { + @Suppress("DEPRECATION") + super.onReceivedError(view, errorCode, description, failingUrl) + onError(description) + } + + override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { + if (url?.startsWith("js:") == true) { + val javascriptResponse = parseJsonFromUrl(url) + val response = javascriptResponse?.response + if (javascriptResponse?.action == "verifyCallback" && response != null) { + onSuccess(response) + } + } + return true + } + + private fun parseJsonFromUrl(url: String): JavascriptResponse? { + return try { + val json = URLDecoder.decode(url.substringAfter("js:"), "UTF-8") + MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java).fromJson(json) + } catch (e: Exception) { + Timber.e(e, "## shouldOverrideUrlLoading(): failed") + null + } + } + } + } + + private fun showSslErrorDialog(container: Fragment, handler: SslErrorHandler) { + MaterialAlertDialogBuilder(container.requireActivity()) + .setMessage(R.string.ssl_could_not_verify) + .setPositiveButton(R.string.ssl_trust) { _, _ -> + Timber.d("## onReceivedSslError() : the user trusted") + handler.proceed() + } + .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> + Timber.d("## onReceivedSslError() : the user did not trust") + handler.cancel() + } + .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> + if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { + handler.cancel() + Timber.d("## onReceivedSslError() : the user dismisses the trust dialog.") + dialog.dismiss() + return@OnKeyListener true + } + false + }) + .setCancelable(false) + .show() + } +} + +private fun WebResourceResponse.toText() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) reasonPhrase else toString() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt index c9c693ef3bf..a3665a8f40f 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCaptchaFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright 2022 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,35 +16,15 @@ package im.vector.app.features.onboarding.ftueauth -import android.annotation.SuppressLint -import android.content.DialogInterface -import android.graphics.Bitmap -import android.net.http.SslError -import android.os.Build import android.os.Parcelable -import android.view.KeyEvent import android.view.LayoutInflater import android.view.ViewGroup -import android.webkit.SslErrorHandler -import android.webkit.WebResourceRequest -import android.webkit.WebResourceResponse -import android.webkit.WebView -import android.webkit.WebViewClient -import androidx.core.view.isVisible import com.airbnb.mvrx.args -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import im.vector.app.R -import im.vector.app.core.utils.AssetReader -import im.vector.app.databinding.FragmentLoginCaptchaBinding -import im.vector.app.features.login.JavascriptResponse +import im.vector.app.databinding.FragmentFtueLoginCaptchaBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.di.MoshiProvider -import timber.log.Timber -import java.net.URLDecoder -import java.util.Formatter import javax.inject.Inject @Parcelize @@ -53,141 +33,17 @@ data class FtueAuthCaptchaFragmentArgument( ) : Parcelable /** - * In this screen, the user is asked to confirm he is not a robot + * In this screen, the user is asked to confirm they are not a robot */ class FtueAuthCaptchaFragment @Inject constructor( - private val assetReader: AssetReader -) : AbstractFtueAuthFragment() { - - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginCaptchaBinding { - return FragmentLoginCaptchaBinding.inflate(inflater, container, false) - } + private val captchaWebview: CaptchaWebview +) : AbstractFtueAuthFragment() { private val params: FtueAuthCaptchaFragmentArgument by args() - private var isWebViewLoaded = false - @SuppressLint("SetJavaScriptEnabled") - private fun setupWebView(state: OnboardingViewState) { - views.loginCaptchaWevView.settings.javaScriptEnabled = true - - val reCaptchaPage = assetReader.readAssetFile("reCaptchaPage.html") ?: error("missing asset reCaptchaPage.html") - - val html = Formatter().format(reCaptchaPage, params.siteKey).toString() - val mime = "text/html" - val encoding = "utf-8" - - val homeServerUrl = state.homeServerUrl ?: error("missing url of homeserver") - views.loginCaptchaWevView.loadDataWithBaseURL(homeServerUrl, html, mime, encoding, null) - views.loginCaptchaWevView.requestLayout() - - views.loginCaptchaWevView.webViewClient = object : WebViewClient() { - override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { - super.onPageStarted(view, url, favicon) - - if (!isAdded) { - return - } - - // Show loader - views.loginCaptchaProgress.isVisible = true - } - - override fun onPageFinished(view: WebView, url: String) { - super.onPageFinished(view, url) - - if (!isAdded) { - return - } - - // Hide loader - views.loginCaptchaProgress.isVisible = false - } - - override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) { - Timber.d("## onReceivedSslError() : ${error.certificate}") - - if (!isAdded) { - return - } - - MaterialAlertDialogBuilder(requireActivity()) - .setMessage(R.string.ssl_could_not_verify) - .setPositiveButton(R.string.ssl_trust) { _, _ -> - Timber.d("## onReceivedSslError() : the user trusted") - handler.proceed() - } - .setNegativeButton(R.string.ssl_do_not_trust) { _, _ -> - Timber.d("## onReceivedSslError() : the user did not trust") - handler.cancel() - } - .setOnKeyListener(DialogInterface.OnKeyListener { dialog, keyCode, event -> - if (event.action == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { - handler.cancel() - Timber.d("## onReceivedSslError() : the user dismisses the trust dialog.") - dialog.dismiss() - return@OnKeyListener true - } - false - }) - .setCancelable(false) - .show() - } - - // common error message - private fun onError(errorMessage: String) { - Timber.e("## onError() : $errorMessage") - - // TODO - // Toast.makeText(this@AccountCreationCaptchaActivity, errorMessage, Toast.LENGTH_LONG).show() - - // on error case, close this activity - // runOnUiThread(Runnable { finish() }) - } - - @SuppressLint("NewApi") - override fun onReceivedHttpError(view: WebView, request: WebResourceRequest, errorResponse: WebResourceResponse) { - super.onReceivedHttpError(view, request, errorResponse) - - if (request.url.toString().endsWith("favicon.ico")) { - // Ignore this error - return - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - onError(errorResponse.reasonPhrase) - } else { - onError(errorResponse.toString()) - } - } - - override fun onReceivedError(view: WebView, errorCode: Int, description: String, failingUrl: String) { - @Suppress("DEPRECATION") - super.onReceivedError(view, errorCode, description, failingUrl) - onError(description) - } - - override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean { - if (url?.startsWith("js:") == true) { - var json = url.substring(3) - var javascriptResponse: JavascriptResponse? = null - - try { - // URL decode - json = URLDecoder.decode(json, "UTF-8") - javascriptResponse = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java).fromJson(json) - } catch (e: Exception) { - Timber.e(e, "## shouldOverrideUrlLoading(): failed") - } - - val response = javascriptResponse?.response - if (javascriptResponse?.action == "verifyCallback" && response != null) { - viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CaptchaDone(response))) - } - } - return true - } - } + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueLoginCaptchaBinding { + return FragmentFtueLoginCaptchaBinding.inflate(inflater, container, false) } override fun resetViewModel() { @@ -196,7 +52,9 @@ class FtueAuthCaptchaFragment @Inject constructor( override fun updateWithState(state: OnboardingViewState) { if (!isWebViewLoaded) { - setupWebView(state) + captchaWebview.setupWebView(this, views.loginCaptchaWevView, views.loginCaptchaProgress, params.siteKey, state) { + viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CaptchaDone(it))) + } isWebViewLoaded = true } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt index 3a7d51d14ba..0755f18c8c2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedRegisterFragment.kt @@ -36,12 +36,13 @@ import im.vector.app.core.extensions.hasSurroundingSpaces import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.hidePassword import im.vector.app.core.extensions.realignPercentagesToParent -import im.vector.app.databinding.FragmentFtueSignUpCombinedBinding +import im.vector.app.core.extensions.toReducedUrl +import im.vector.app.databinding.FragmentFtueCombinedRegisterBinding import im.vector.app.features.login.LoginMode import im.vector.app.features.login.SSORedirectRouterActivity -import im.vector.app.features.login.ServerType import im.vector.app.features.login.SocialLoginButtonsView import im.vector.app.features.onboarding.OnboardingAction +import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.launchIn @@ -55,17 +56,19 @@ import org.matrix.android.sdk.api.failure.isUsernameInUse import org.matrix.android.sdk.api.failure.isWeakPassword import javax.inject.Inject -class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAuthFragment() { +class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAuthFragment() { - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueSignUpCombinedBinding { - return FragmentFtueSignUpCombinedBinding.inflate(inflater, container, false) + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueCombinedRegisterBinding { + return FragmentFtueCombinedRegisterBinding.inflate(inflater, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) setupSubmitButton() - views.createAccountRoot.realignPercentagesToParent() + views.editServerButton.debouncedClicks { + viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.EditServerSelection)) + } views.createAccountPasswordInput.editText().setOnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_DONE) { @@ -164,6 +167,9 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu setupUi(state) setupAutoFill() + views.selectedServerName.text = state.selectedHomeserver.userFacingUrl.toReducedUrl() + views.selectedServerDescription.text = state.selectedHomeserver.description + if (state.isLoading) { // Ensure password is hidden views.createAccountPasswordInput.editText().hidePassword() @@ -171,8 +177,8 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu } private fun setupUi(state: OnboardingViewState) { - when (state.loginMode) { - is LoginMode.SsoAndPassword -> renderSsoProviders(state.deviceId, state.loginMode.ssoIdentityProviders) + when (state.selectedHomeserver.preferredLoginMode) { + is LoginMode.SsoAndPassword -> renderSsoProviders(state.deviceId, state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders) else -> hideSsoProviders() } } @@ -201,6 +207,6 @@ class FtueAuthCombinedRegisterFragment @Inject constructor() : AbstractSSOFtueAu views.createAccountPasswordInput.setAutofillHints(HintConstants.AUTOFILL_HINT_NEW_PASSWORD) } } -} -private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = serverType == ServerType.MatrixOrg + private fun OnboardingViewState.isNumericOnlyUserIdForbidden() = selectedHomeserver.userFacingUrl == getString(R.string.matrix_org_server_url) +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt new file mode 100644 index 00000000000..2e6057288a4 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthCombinedServerSelectionFragment.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.EditorInfo +import androidx.lifecycle.lifecycleScope +import im.vector.app.R +import im.vector.app.core.extensions.content +import im.vector.app.core.extensions.editText +import im.vector.app.core.extensions.realignPercentagesToParent +import im.vector.app.core.extensions.toReducedUrl +import im.vector.app.core.utils.ensureProtocol +import im.vector.app.core.utils.ensureTrailingSlash +import im.vector.app.core.utils.openUrlInExternalBrowser +import im.vector.app.databinding.FragmentFtueServerSelectionCombinedBinding +import im.vector.app.features.onboarding.OnboardingAction +import im.vector.app.features.onboarding.OnboardingViewEvents +import im.vector.app.features.onboarding.OnboardingViewState +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import org.matrix.android.sdk.api.failure.isHomeserverUnavailable +import reactivecircus.flowbinding.android.widget.textChanges +import javax.inject.Inject + +class FtueAuthCombinedServerSelectionFragment @Inject constructor() : AbstractFtueAuthFragment() { + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueServerSelectionCombinedBinding { + return FragmentFtueServerSelectionCombinedBinding.inflate(inflater, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + setupViews() + } + + private fun setupViews() { + views.chooseServerRoot.realignPercentagesToParent() + views.chooseServerToolbar.setNavigationOnClickListener { + viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnBack)) + } + views.chooseServerInput.editText?.setOnEditorActionListener { _, actionId, _ -> + when (actionId) { + EditorInfo.IME_ACTION_DONE -> { + updateServerUrl() + } + } + false + } + views.chooseServerGetInTouch.debouncedClicks { openUrlInExternalBrowser(requireContext(), getString(R.string.ftue_ems_url)) } + views.chooseServerSubmit.debouncedClicks { updateServerUrl() } + views.chooseServerInput.editText().textChanges() + .onEach { views.chooseServerInput.error = null } + .launchIn(lifecycleScope) + } + + private fun updateServerUrl() { + viewModel.handle(OnboardingAction.HomeServerChange.EditHomeServer(views.chooseServerInput.content().ensureProtocol().ensureTrailingSlash())) + } + + override fun resetViewModel() { + // do nothing + } + + override fun updateWithState(state: OnboardingViewState) { + if (views.chooseServerInput.content().isEmpty()) { + val userUrlInput = state.selectedHomeserver.userFacingUrl?.toReducedUrlKeepingSchemaIfInsecure() + views.chooseServerInput.editText().setText(userUrlInput) + } + } + + override fun onError(throwable: Throwable) { + views.chooseServerInput.error = when { + throwable.isHomeserverUnavailable() -> getString(R.string.login_error_homeserver_not_found) + else -> errorFormatter.toHumanReadable(throwable) + } + } + + private fun String.toReducedUrlKeepingSchemaIfInsecure() = toReducedUrl(keepSchema = this.startsWith("http://")) +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyStyleCaptchaFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyStyleCaptchaFragment.kt new file mode 100644 index 00000000000..2accab00e0f --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLegacyStyleCaptchaFragment.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth + +import android.os.Parcelable +import android.view.LayoutInflater +import android.view.ViewGroup +import com.airbnb.mvrx.args +import im.vector.app.databinding.FragmentLoginCaptchaBinding +import im.vector.app.features.onboarding.OnboardingAction +import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.app.features.onboarding.RegisterAction +import kotlinx.parcelize.Parcelize +import javax.inject.Inject + +@Parcelize +data class FtueAuthLegacyStyleCaptchaFragmentArgument( + val siteKey: String +) : Parcelable + +/** + * In this screen, the user is asked to confirm they are not a robot + */ +class FtueAuthLegacyStyleCaptchaFragment @Inject constructor( + private val captchaWebview: CaptchaWebview +) : AbstractFtueAuthFragment() { + + private val params: FtueAuthLegacyStyleCaptchaFragmentArgument by args() + private var isWebViewLoaded = false + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginCaptchaBinding { + return FragmentLoginCaptchaBinding.inflate(inflater, container, false) + } + + override fun resetViewModel() { + viewModel.handle(OnboardingAction.ResetAuthenticationAttempt) + } + + override fun updateWithState(state: OnboardingViewState) { + if (!isWebViewLoaded) { + captchaWebview.setupWebView(this, views.loginCaptchaWevView, views.loginCaptchaProgress, params.siteKey, state) { + viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.CaptchaDone(it))) + } + isWebViewLoaded = true + } + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt index e561f85f25b..4888b439462 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthLoginFragment.kt @@ -184,7 +184,7 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment< ServerType.MatrixOrg -> { views.loginServerIcon.isVisible = true views.loginServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) - views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl()) + views.loginTitle.text = getString(resId, state.selectedHomeserver.userFacingUrl.toReducedUrl()) views.loginNotice.text = getString(R.string.login_server_matrix_org_text) } ServerType.EMS -> { @@ -195,16 +195,16 @@ class FtueAuthLoginFragment @Inject constructor() : AbstractSSOFtueAuthFragment< } ServerType.Other -> { views.loginServerIcon.isVisible = false - views.loginTitle.text = getString(resId, state.homeServerUrlFromUser.toReducedUrl()) + views.loginTitle.text = getString(resId, state.selectedHomeserver.userFacingUrl.toReducedUrl()) views.loginNotice.text = getString(R.string.login_server_other_text) } ServerType.Unknown -> Unit /* Should not happen */ } views.loginPasswordNotice.isVisible = false - if (state.loginMode is LoginMode.SsoAndPassword) { + if (state.selectedHomeserver.preferredLoginMode is LoginMode.SsoAndPassword) { views.loginSocialLoginContainer.isVisible = true - views.loginSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders?.sorted() + views.loginSocialLoginButtons.ssoIdentityProviders = state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders?.sorted() views.loginSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener { override fun onProviderSelected(id: String?) { viewModel.getSsoUrl( diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt index b612ec34b57..4ec02f677a3 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthResetPasswordFragment.kt @@ -59,7 +59,7 @@ class FtueAuthResetPasswordFragment @Inject constructor() : AbstractFtueAuthFrag } private fun setupUi(state: OnboardingViewState) { - views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.homeServerUrlFromUser.toReducedUrl()) + views.resetPasswordTitle.text = getString(R.string.login_reset_password_on, state.selectedHomeserver.userFacingUrl.toReducedUrl()) } private fun setupSubmitButton() { diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt index 2cae9743a7c..df304d028d2 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthServerUrlFormFragment.kt @@ -139,7 +139,7 @@ class FtueAuthServerUrlFormFragment @Inject constructor() : AbstractFtueAuthFrag } else -> { views.loginServerUrlFormHomeServerUrl.setText(serverUrl, false /* to avoid completion dialog flicker*/) - viewModel.handle(OnboardingAction.UpdateHomeServer(serverUrl)) + viewModel.handle(OnboardingAction.HomeServerChange.SelectHomeServer(serverUrl)) } } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt index e9ae5022e23..dda5e0c36ad 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthSignUpSignInSelectionFragment.kt @@ -20,6 +20,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.annotation.DrawableRes import androidx.core.view.isVisible import com.airbnb.mvrx.withState import im.vector.app.R @@ -55,32 +56,30 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF views.loginSignupSigninSignIn.setOnClickListener { signIn() } } - private fun setupUi(state: OnboardingViewState) { + private fun render(state: OnboardingViewState) { when (state.serverType) { - ServerType.MatrixOrg -> { - views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) - views.loginSignupSigninServerIcon.isVisible = true - views.loginSignupSigninTitle.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) - views.loginSignupSigninText.text = getString(R.string.login_server_matrix_org_text) - } - ServerType.EMS -> { - views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_element_matrix_services) - views.loginSignupSigninServerIcon.isVisible = true - views.loginSignupSigninTitle.text = getString(R.string.login_connect_to_modular) - views.loginSignupSigninText.text = state.homeServerUrlFromUser.toReducedUrl() - } - ServerType.Other -> { - views.loginSignupSigninServerIcon.isVisible = false - views.loginSignupSigninTitle.text = getString(R.string.login_server_other_title) - views.loginSignupSigninText.text = getString(R.string.login_connect_to, state.homeServerUrlFromUser.toReducedUrl()) - } + ServerType.MatrixOrg -> renderServerInformation( + icon = R.drawable.ic_logo_matrix_org, + title = getString(R.string.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()), + subtitle = getString(R.string.login_server_matrix_org_text) + ) + ServerType.EMS -> renderServerInformation( + icon = R.drawable.ic_logo_element_matrix_services, + title = getString(R.string.login_connect_to_modular), + subtitle = state.selectedHomeserver.userFacingUrl.toReducedUrl() + ) + ServerType.Other -> renderServerInformation( + icon = null, + title = getString(R.string.login_server_other_title), + subtitle = getString(R.string.login_connect_to, state.selectedHomeserver.userFacingUrl.toReducedUrl()) + ) ServerType.Unknown -> Unit /* Should not happen */ } - when (state.loginMode) { + when (state.selectedHomeserver.preferredLoginMode) { is LoginMode.SsoAndPassword -> { views.loginSignupSigninSignInSocialLoginContainer.isVisible = true - views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.loginMode.ssoIdentityProviders()?.sorted() + views.loginSignupSigninSocialLoginButtons.ssoIdentityProviders = state.selectedHomeserver.preferredLoginMode.ssoIdentityProviders()?.sorted() views.loginSignupSigninSocialLoginButtons.listener = object : SocialLoginButtonsView.InteractionListener { override fun onProviderSelected(id: String?) { viewModel.getSsoUrl( @@ -100,8 +99,16 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF } } + private fun renderServerInformation(@DrawableRes icon: Int?, title: String, subtitle: String) { + icon?.let { views.loginSignupSigninServerIcon.setImageResource(it) } + views.loginSignupSigninServerIcon.isVisible = icon != null + views.loginSignupSigninServerIcon.setImageResource(R.drawable.ic_logo_matrix_org) + views.loginSignupSigninTitle.text = title + views.loginSignupSigninText.text = subtitle + } + private fun setupButtons(state: OnboardingViewState) { - when (state.loginMode) { + when (state.selectedHomeserver.preferredLoginMode) { is LoginMode.Sso -> { // change to only one button that is sign in with sso views.loginSignupSigninSubmit.text = getString(R.string.login_signin_sso) @@ -115,7 +122,7 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF } private fun submit() = withState(viewModel) { state -> - if (state.loginMode is LoginMode.Sso) { + if (state.selectedHomeserver.preferredLoginMode is LoginMode.Sso) { viewModel.getSsoUrl( redirectUrl = SSORedirectRouterActivity.VECTOR_REDIRECT_URL, deviceId = state.deviceId, @@ -136,7 +143,7 @@ class FtueAuthSignUpSignInSelectionFragment @Inject constructor() : AbstractSSOF } override fun updateWithState(state: OnboardingViewState) { - setupUi(state) + render(state) setupButtons(state) } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt index 4c7bf472338..d5816762df5 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthVariant.kt @@ -17,6 +17,7 @@ package im.vector.app.features.onboarding.ftueauth import android.content.Intent +import android.os.Parcelable import android.view.View import android.view.ViewGroup import androidx.core.view.ViewCompat @@ -51,8 +52,9 @@ import im.vector.app.features.onboarding.OnboardingVariant import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewModel import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthLegacyStyleTermsFragment import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragment -import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsFragmentArgument +import im.vector.app.features.onboarding.ftueauth.terms.FtueAuthTermsLegacyStyleFragmentArgument import org.matrix.android.sdk.api.auth.registration.FlowResult import org.matrix.android.sdk.api.auth.registration.Stage import org.matrix.android.sdk.api.extensions.tryOrNull @@ -201,20 +203,18 @@ class FtueAuthVariant( is OnboardingViewEvents.OnSendEmailSuccess -> { // Pop the enter email Fragment supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE) - activity.addFragmentToBackstack(views.loginFragmentContainer, + addRegistrationStageFragmentToBackstack( FtueAuthWaitForEmailFragment::class.java, FtueAuthWaitForEmailFragmentArgument(viewEvents.email), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) + ) } is OnboardingViewEvents.OnSendMsisdnSuccess -> { // Pop the enter Msisdn Fragment supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE) - activity.addFragmentToBackstack(views.loginFragmentContainer, + addRegistrationStageFragmentToBackstack( FtueAuthGenericTextInputFormFragment::class.java, FtueAuthGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.ConfirmMsisdn, true, viewEvents.msisdn), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) + ) } is OnboardingViewEvents.Failure, is OnboardingViewEvents.Loading -> @@ -233,16 +233,19 @@ class FtueAuthVariant( OnboardingViewEvents.OnChooseProfilePicture -> onChooseProfilePicture() OnboardingViewEvents.OnPersonalizationComplete -> onPersonalizationComplete() OnboardingViewEvents.OnBack -> activity.popBackstack() + OnboardingViewEvents.EditServerSelection -> { + activity.addFragmentToBackstack( + views.loginFragmentContainer, + FtueAuthCombinedServerSelectionFragment::class.java, + option = commonOption + ) + } + OnboardingViewEvents.OnHomeserverEdited -> activity.popBackstack() } } private fun openCombinedRegister() { - activity.addFragmentToBackstack( - views.loginFragmentContainer, - FtueAuthCombinedRegisterFragment::class.java, - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption - ) + addRegistrationStageFragmentToBackstack(FtueAuthCombinedRegisterFragment::class.java) } private fun registrationShouldFallback(registrationFlowResult: OnboardingViewEvents.RegistrationFlowResult) = @@ -299,18 +302,18 @@ class FtueAuthVariant( private fun handleSignInSelected(state: OnboardingViewState) { if (isForceLoginFallbackEnabled) { - onLoginModeNotSupported(state.loginModeSupportedTypes) + onLoginModeNotSupported(state.selectedHomeserver.supportedLoginTypes) } else { disambiguateLoginMode(state) } } - private fun disambiguateLoginMode(state: OnboardingViewState) = when (state.loginMode) { + private fun disambiguateLoginMode(state: OnboardingViewState) = when (state.selectedHomeserver.preferredLoginMode) { LoginMode.Unknown, is LoginMode.Sso -> error("Developer error") is LoginMode.SsoAndPassword, LoginMode.Password -> openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG) - LoginMode.Unsupported -> onLoginModeNotSupported(state.loginModeSupportedTypes) + LoginMode.Unsupported -> onLoginModeNotSupported(state.selectedHomeserver.supportedLoginTypes) } private fun openAuthLoginFragmentWithTag(tag: String) { @@ -331,7 +334,7 @@ class FtueAuthVariant( private fun handleSignInWithMatrixId(state: OnboardingViewState) { if (isForceLoginFallbackEnabled) { - onLoginModeNotSupported(state.loginModeSupportedTypes) + onLoginModeNotSupported(state.selectedHomeserver.supportedLoginTypes) } else { openAuthLoginFragmentWithTag(FRAGMENT_LOGIN_TAG) } @@ -374,30 +377,46 @@ class FtueAuthVariant( supportFragmentManager.popBackStack(FRAGMENT_REGISTRATION_STAGE_TAG, FragmentManager.POP_BACK_STACK_INCLUSIVE) when (stage) { - is Stage.ReCaptcha -> activity.addFragmentToBackstack(views.loginFragmentContainer, - FtueAuthCaptchaFragment::class.java, - FtueAuthCaptchaFragmentArgument(stage.publicKey), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) - is Stage.Email -> activity.addFragmentToBackstack(views.loginFragmentContainer, + is Stage.ReCaptcha -> onCaptcha(stage) + is Stage.Email -> addRegistrationStageFragmentToBackstack( FtueAuthGenericTextInputFormFragment::class.java, FtueAuthGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetEmail, stage.mandatory), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) - is Stage.Msisdn -> activity.addFragmentToBackstack(views.loginFragmentContainer, + ) + is Stage.Msisdn -> addRegistrationStageFragmentToBackstack( FtueAuthGenericTextInputFormFragment::class.java, FtueAuthGenericTextInputFormFragmentArgument(TextInputFormFragmentMode.SetMsisdn, stage.mandatory), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) - is Stage.Terms -> activity.addFragmentToBackstack(views.loginFragmentContainer, - FtueAuthTermsFragment::class.java, - FtueAuthTermsFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))), - tag = FRAGMENT_REGISTRATION_STAGE_TAG, - option = commonOption) + ) + is Stage.Terms -> onTerms(stage) else -> Unit // Should not happen } } + private fun onTerms(stage: Stage.Terms) { + when { + vectorFeatures.isOnboardingCombinedRegisterEnabled() -> addRegistrationStageFragmentToBackstack( + FtueAuthTermsFragment::class.java, + FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))), + ) + else -> addRegistrationStageFragmentToBackstack( + FtueAuthLegacyStyleTermsFragment::class.java, + FtueAuthTermsLegacyStyleFragmentArgument(stage.policies.toLocalizedLoginTerms(activity.getString(R.string.resources_language))), + ) + } + } + + private fun onCaptcha(stage: Stage.ReCaptcha) { + when { + vectorFeatures.isOnboardingCombinedRegisterEnabled() -> addRegistrationStageFragmentToBackstack( + FtueAuthCaptchaFragment::class.java, + FtueAuthCaptchaFragmentArgument(stage.publicKey), + ) + else -> addRegistrationStageFragmentToBackstack( + FtueAuthLegacyStyleCaptchaFragment::class.java, + FtueAuthLegacyStyleCaptchaFragmentArgument(stage.publicKey), + ) + } + } + private fun onAccountSignedIn() { navigateToHome(createdAccount = false) } @@ -439,4 +458,14 @@ class FtueAuthVariant( useCustomAnimation = true ) } + + private fun addRegistrationStageFragmentToBackstack(fragmentClass: Class, params: Parcelable? = null) { + activity.addFragmentToBackstack( + views.loginFragmentContainer, + fragmentClass, + params, + tag = FRAGMENT_REGISTRATION_STAGE_TAG, + option = commonOption + ) + } } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt index 69b002c2711..26b9a38d835 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthWebFragment.kt @@ -40,7 +40,7 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents import im.vector.app.features.onboarding.OnboardingViewState import org.matrix.android.sdk.api.auth.data.Credentials -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import timber.log.Timber import java.net.URLDecoder import javax.inject.Inject @@ -200,7 +200,7 @@ class FtueAuthWebFragment @Inject constructor( try { // URL decode json = URLDecoder.decode(json, "UTF-8") - val adapter = MoshiProvider.providesMoshi().adapter(JavascriptResponse::class.java) + val adapter = MatrixJsonParser.getMoshi().adapter(JavascriptResponse::class.java) javascriptResponse = adapter.fromJson(json) } catch (e: Exception) { Timber.e(e, "## shouldOverrideUrlLoading() : fromJson failed") diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthLegacyStyleTermsFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthLegacyStyleTermsFragment.kt new file mode 100755 index 00000000000..727e3d5cbd8 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthLegacyStyleTermsFragment.kt @@ -0,0 +1,124 @@ +/* + * Copyright 2018 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.onboarding.ftueauth.terms + +import android.os.Bundle +import android.os.Parcelable +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.airbnb.mvrx.args +import im.vector.app.core.extensions.cleanup +import im.vector.app.core.extensions.configureWith +import im.vector.app.core.extensions.toReducedUrl +import im.vector.app.core.utils.openUrlInChromeCustomTab +import im.vector.app.databinding.FragmentLoginTermsBinding +import im.vector.app.features.login.terms.LocalizedFlowDataLoginTermsChecked +import im.vector.app.features.login.terms.LoginTermsViewState +import im.vector.app.features.login.terms.PolicyController +import im.vector.app.features.onboarding.OnboardingAction +import im.vector.app.features.onboarding.OnboardingViewState +import im.vector.app.features.onboarding.RegisterAction +import im.vector.app.features.onboarding.ftueauth.AbstractFtueAuthFragment +import kotlinx.parcelize.Parcelize +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms +import javax.inject.Inject + +@Parcelize +data class FtueAuthTermsLegacyStyleFragmentArgument( + val localizedFlowDataLoginTerms: List +) : Parcelable + +/** + * LoginTermsFragment displays the list of policies the user has to accept + */ +class FtueAuthLegacyStyleTermsFragment @Inject constructor( + private val policyController: PolicyController +) : AbstractFtueAuthFragment(), + PolicyController.PolicyControllerListener { + + private val params: FtueAuthTermsLegacyStyleFragmentArgument by args() + + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginTermsBinding { + return FragmentLoginTermsBinding.inflate(inflater, container, false) + } + + private var loginTermsViewState: LoginTermsViewState = LoginTermsViewState(emptyList()) + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setupViews() + views.loginTermsPolicyList.configureWith(policyController) + policyController.listener = this + + val list = ArrayList() + + params.localizedFlowDataLoginTerms + .forEach { + list.add(LocalizedFlowDataLoginTermsChecked(it)) + } + + loginTermsViewState = LoginTermsViewState(list) + } + + private fun setupViews() { + views.loginTermsSubmit.setOnClickListener { submit() } + } + + override fun onDestroyView() { + views.loginTermsPolicyList.cleanup() + policyController.listener = null + super.onDestroyView() + } + + private fun renderState() { + policyController.setData(loginTermsViewState.localizedFlowDataLoginTermsChecked) + views.loginTermsSubmit.isEnabled = loginTermsViewState.allChecked() + } + + override fun setChecked(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms, isChecked: Boolean) { + if (isChecked) { + loginTermsViewState.check(localizedFlowDataLoginTerms) + } else { + loginTermsViewState.uncheck(localizedFlowDataLoginTerms) + } + + renderState() + } + + override fun openPolicy(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms) { + localizedFlowDataLoginTerms.localizedUrl + ?.takeIf { it.isNotBlank() } + ?.let { + openUrlInChromeCustomTab(requireContext(), null, it) + } + } + + private fun submit() { + viewModel.handle(OnboardingAction.PostRegisterAction(RegisterAction.AcceptTerms)) + } + + override fun updateWithState(state: OnboardingViewState) { + policyController.homeServer = state.selectedHomeserver.userFacingUrl.toReducedUrl() + renderState() + } + + override fun resetViewModel() { + viewModel.handle(OnboardingAction.ResetAuthenticationAttempt) + } +} diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt old mode 100755 new mode 100644 index f6a7769cbdd..4a25e35537a --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/terms/FtueAuthTermsFragment.kt @@ -1,5 +1,5 @@ /* - * Copyright 2018 New Vector Ltd + * Copyright (c) 2022 New Vector Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,16 +17,18 @@ package im.vector.app.features.onboarding.ftueauth.terms import android.os.Bundle -import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.doOnLayout import com.airbnb.mvrx.args +import im.vector.app.R import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.toReducedUrl import im.vector.app.core.utils.openUrlInChromeCustomTab -import im.vector.app.databinding.FragmentLoginTermsBinding +import im.vector.app.databinding.FragmentFtueLoginTermsBinding import im.vector.app.features.login.terms.LocalizedFlowDataLoginTermsChecked import im.vector.app.features.login.terms.LoginTermsViewState import im.vector.app.features.login.terms.PolicyController @@ -34,50 +36,46 @@ import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewState import im.vector.app.features.onboarding.RegisterAction import im.vector.app.features.onboarding.ftueauth.AbstractFtueAuthFragment -import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.internal.auth.registration.LocalizedFlowDataLoginTerms +import org.matrix.android.sdk.api.auth.data.LocalizedFlowDataLoginTerms import javax.inject.Inject - -@Parcelize -data class FtueAuthTermsFragmentArgument( - val localizedFlowDataLoginTerms: List -) : Parcelable +import kotlin.math.roundToInt /** * LoginTermsFragment displays the list of policies the user has to accept */ class FtueAuthTermsFragment @Inject constructor( private val policyController: PolicyController -) : AbstractFtueAuthFragment(), +) : AbstractFtueAuthFragment(), PolicyController.PolicyControllerListener { - private val params: FtueAuthTermsFragmentArgument by args() + private val params: FtueAuthTermsLegacyStyleFragmentArgument by args() - override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLoginTermsBinding { - return FragmentLoginTermsBinding.inflate(inflater, container, false) + override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentFtueLoginTermsBinding { + return FragmentFtueLoginTermsBinding.inflate(inflater, container, false) } private var loginTermsViewState: LoginTermsViewState = LoginTermsViewState(emptyList()) override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupViews() - views.loginTermsPolicyList.configureWith(policyController) - policyController.listener = this - val list = ArrayList() - params.localizedFlowDataLoginTerms .forEach { list.add(LocalizedFlowDataLoginTermsChecked(it)) } - loginTermsViewState = LoginTermsViewState(list) } private fun setupViews() { - views.loginTermsSubmit.setOnClickListener { submit() } + views.termsSubmit.setOnClickListener { submit() } + views.loginTermsPolicyList.setHasFixedSize(false) + views.loginTermsPolicyList.configureWith(policyController, hasFixedSize = false, dividerDrawable = R.drawable.divider_horizontal) + views.termsGutterStart.doOnLayout { + val gutterSize = views.contentRoot.width * (views.termsGutterStart.layoutParams as ConstraintLayout.LayoutParams).guidePercent + policyController.horizontalPadding = gutterSize.roundToInt() + } + policyController.listener = this } override fun onDestroyView() { @@ -90,7 +88,7 @@ class FtueAuthTermsFragment @Inject constructor( policyController.setData(loginTermsViewState.localizedFlowDataLoginTermsChecked) // Button is enabled only if all checkboxes are checked - views.loginTermsSubmit.isEnabled = loginTermsViewState.allChecked() + views.termsSubmit.isEnabled = loginTermsViewState.allChecked() } override fun setChecked(localizedFlowDataLoginTerms: LocalizedFlowDataLoginTerms, isChecked: Boolean) { @@ -116,7 +114,7 @@ class FtueAuthTermsFragment @Inject constructor( } override fun updateWithState(state: OnboardingViewState) { - policyController.homeServer = state.homeServerUrlFromUser.toReducedUrl() + policyController.homeServer = state.selectedHomeserver.userFacingUrl.toReducedUrl() renderState() } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index bf007ea1b04..8b514f4003e 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -51,8 +51,8 @@ import org.json.JSONException import org.json.JSONObject import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.util.JsonDict +import org.matrix.android.sdk.api.util.MatrixJsonParser import org.matrix.android.sdk.api.util.MimeTypes -import org.matrix.android.sdk.internal.di.MoshiProvider import timber.log.Timber import java.io.File import java.io.IOException @@ -98,7 +98,7 @@ class BugReporter @Inject constructor( // boolean to cancel the bug report private val mIsCancelled = false - val adapter = MoshiProvider.providesMoshi() + val adapter = MatrixJsonParser.getMoshi() .adapter(Types.newParameterizedType(Map::class.java, String::class.java, Any::class.java)) /** diff --git a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownMapper.kt b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownMapper.kt index 899a7d3fe62..06661cb9290 100644 --- a/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownMapper.kt +++ b/vector/src/main/java/im/vector/app/features/raw/wellknown/ElementWellKnownMapper.kt @@ -18,11 +18,11 @@ package im.vector.app.features.raw.wellknown import com.squareup.moshi.JsonAdapter import org.matrix.android.sdk.api.extensions.tryOrNull -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser object ElementWellKnownMapper { - val adapter: JsonAdapter = MoshiProvider.providesMoshi().adapter(ElementWellKnown::class.java) + val adapter: JsonAdapter = MatrixJsonParser.getMoshi().adapter(ElementWellKnown::class.java) fun from(value: String): ElementWellKnown? { return tryOrNull("Unable to parse well-known data") { adapter.fromJson(value) } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt index d9ed6d227a4..5fee420b211 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileFragment.kt @@ -47,6 +47,8 @@ import im.vector.app.databinding.DialogBaseEditTextBinding import im.vector.app.databinding.DialogShareQrCodeBinding import im.vector.app.databinding.FragmentMatrixProfileBinding import im.vector.app.databinding.ViewStubRoomMemberProfileHeaderBinding +import im.vector.app.features.MainActivity +import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.crypto.verification.VerificationBottomSheet import im.vector.app.features.displayname.getBestName @@ -57,7 +59,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorPr import im.vector.app.features.roommemberprofile.devices.DeviceListBottomSheet import im.vector.app.features.roommemberprofile.powerlevel.EditPowerLevelDialogs import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.room.powerlevels.Role import org.matrix.android.sdk.api.util.MatrixItem import javax.inject.Inject @@ -131,13 +133,20 @@ class RoomMemberProfileFragment @Inject constructor( is RoomMemberProfileViewEvents.OnKickActionSuccess -> Unit is RoomMemberProfileViewEvents.OnSetPowerLevelSuccess -> Unit is RoomMemberProfileViewEvents.OnBanActionSuccess -> Unit - is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> Unit + is RoomMemberProfileViewEvents.OnIgnoreActionSuccess -> handleOnIgnoreActionSuccess(it) is RoomMemberProfileViewEvents.OnInviteActionSuccess -> Unit } } setupLongClicks() } + private fun handleOnIgnoreActionSuccess(action: RoomMemberProfileViewEvents.OnIgnoreActionSuccess) { + if (action.shouldPerformInitialSync) { + // A user has been un-ignored, perform a initial sync + MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + } + } + private fun setupLongClicks() { headerViews.memberProfileNameView.copyOnLongClick() headerViews.memberProfileIdView.copyOnLongClick() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt index efe23eeff02..1857f5cdc4f 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewEvents.kt @@ -25,7 +25,7 @@ sealed class RoomMemberProfileViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : RoomMemberProfileViewEvents() data class Failure(val throwable: Throwable) : RoomMemberProfileViewEvents() - object OnIgnoreActionSuccess : RoomMemberProfileViewEvents() + data class OnIgnoreActionSuccess(val shouldPerformInitialSync: Boolean) : RoomMemberProfileViewEvents() object OnSetPowerLevelSuccess : RoomMemberProfileViewEvents() object OnInviteActionSuccess : RoomMemberProfileViewEvents() object OnKickActionSuccess : RoomMemberProfileViewEvents() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt index 1f23fec3277..addc2c71efa 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/RoomMemberProfileViewModel.kt @@ -55,7 +55,7 @@ import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.api.session.room.powerlevels.Role -import org.matrix.android.sdk.api.util.MatrixItem +import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.api.util.toOptional import org.matrix.android.sdk.flow.flow @@ -112,8 +112,8 @@ class RoomMemberProfileViewModel @AssistedInject constructor( session.flow().liveUserCryptoDevices(initialState.userId) .map { Pair( - it.fold(true, { prev, dev -> prev && dev.isVerified }), - it.fold(true, { prev, dev -> prev && (dev.trustLevel?.crossSigningVerified == true) }) + it.fold(true) { prev, dev -> prev && dev.isVerified }, + it.fold(true) { prev, dev -> prev && (dev.trustLevel?.crossSigningVerified == true) } ) } .execute { it -> @@ -327,14 +327,9 @@ class RoomMemberProfileViewModel @AssistedInject constructor( private suspend fun fetchProfileInfo() { val result = runCatchingToAsync { - session.getProfileAsUser(initialState.userId) - .let { - MatrixItem.UserItem( - id = initialState.userId, - displayName = it.displayName, - avatarUrl = it.avatarUrl - ) - } + session.getProfile(initialState.userId) + .let { User.fromJson(initialState.userId, it) } + .toMatrixItem() } setState { @@ -395,7 +390,7 @@ class RoomMemberProfileViewModel @AssistedInject constructor( } else { session.ignoreUserIds(listOf(state.userId)) } - RoomMemberProfileViewEvents.OnIgnoreActionSuccess + RoomMemberProfileViewEvents.OnIgnoreActionSuccess(isIgnored) } catch (failure: Throwable) { RoomMemberProfileViewEvents.Failure(failure) } diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt index fc28b68b79f..c269a4166af 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListAction.kt @@ -17,7 +17,7 @@ package im.vector.app.features.roommemberprofile.devices import im.vector.app.core.platform.VectorViewModelAction -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo sealed class DeviceListAction : VectorViewModelAction { data class SelectDevice(val device: CryptoDeviceInfo) : DeviceListAction() diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt index 03e07a2f820..5c64232a5ac 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListBottomSheetViewModel.kt @@ -31,11 +31,11 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.crypto.crosssigning.MXCrossSigningInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.util.MatrixItem import org.matrix.android.sdk.api.util.toMatrixItem import org.matrix.android.sdk.flow.flow -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo data class DeviceListViewState( val userId: String, diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt index 3bfb210f8de..6a9d053d2a2 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListEpoxyController.kt @@ -34,7 +34,7 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import javax.inject.Inject class DeviceListEpoxyController @Inject constructor(private val stringProvider: StringProvider, diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListFragment.kt index dbf1f195956..48a8a819bc4 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceListFragment.kt @@ -27,7 +27,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.DimensionConverter import im.vector.app.databinding.BottomSheetGenericListBinding -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import javax.inject.Inject class DeviceListFragment @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt index f82ecb6ddff..a7331973723 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoActionFragment.kt @@ -27,7 +27,7 @@ import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.DimensionConverter import im.vector.app.databinding.BottomSheetGenericListBinding -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import javax.inject.Inject class DeviceTrustInfoActionFragment @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt index c7f6e64f5cc..a52f56870ae 100644 --- a/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/roommemberprofile/devices/DeviceTrustInfoEpoxyController.kt @@ -29,7 +29,7 @@ import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationA import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import javax.inject.Inject class DeviceTrustInfoEpoxyController @Inject constructor(private val stringProvider: StringProvider, diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt index e4630dae3fd..372b4e5a70c 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileController.kt @@ -34,7 +34,7 @@ import im.vector.app.features.settings.VectorPreferences import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.image import me.gujun.android.span.span -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.room.model.RoomEncryptionAlgorithm import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 9177f843a04..39440665843 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -54,7 +54,6 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.parcelize.Parcelize -import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState import org.matrix.android.sdk.api.util.toMatrixItem import timber.log.Timber @@ -69,7 +68,6 @@ class RoomProfileFragment @Inject constructor( private val roomProfileController: RoomProfileController, private val avatarRenderer: AvatarRenderer, private val roomDetailPendingActionStore: RoomDetailPendingActionStore, - private val matrixConfiguration: MatrixConfiguration ) : VectorBaseFragment(), RoomProfileController.Callback { @@ -224,7 +222,7 @@ class RoomProfileFragment @Inject constructor( avatarRenderer.render(matrixItem, views.matrixProfileToolbarAvatarImageView) headerViews.roomProfileDecorationImageView.render(it.roomEncryptionTrustLevel) views.matrixProfileDecorationToolbarAvatarImageView.render(it.roomEncryptionTrustLevel) - headerViews.roomProfilePresenceImageView.render(it.isDirect && matrixConfiguration.presenceSyncEnabled, it.directUserPresence) + headerViews.roomProfilePresenceImageView.render(it.isDirect, it.directUserPresence) headerViews.roomProfilePublicImageView.isVisible = it.isPublic && !it.isDirect } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt index 6e0bb12642c..07236fb397a 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListController.kt @@ -27,7 +27,6 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.StringProvider import im.vector.app.features.home.AvatarRenderer import me.gujun.android.span.span -import org.matrix.android.sdk.api.MatrixConfiguration import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary @@ -40,8 +39,7 @@ class RoomMemberListController @Inject constructor( private val avatarRenderer: AvatarRenderer, private val stringProvider: StringProvider, private val colorProvider: ColorProvider, - private val roomMemberSummaryFilter: RoomMemberSummaryFilter, - private val matrixConfiguration: MatrixConfiguration + private val roomMemberSummaryFilter: RoomMemberSummaryFilter ) : TypedEpoxyController() { interface Callback { @@ -124,7 +122,6 @@ class RoomMemberListController @Inject constructor( host: RoomMemberListController, data: RoomMemberListViewState) { val powerLabel = stringProvider.getString(powerLevelCategory.titleRes) - val presenceSyncEnabled = matrixConfiguration.presenceSyncEnabled profileMatrixItemWithPowerLevelWithPresence { id(roomMember.userId) @@ -134,7 +131,7 @@ class RoomMemberListController @Inject constructor( clickListener { host.callback?.onRoomMemberClicked(roomMember) } - showPresence(presenceSyncEnabled) + showPresence(true) userPresence(roomMember.userPresence) powerLevelLabel( span { diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt index c9a70fbef85..1adf35a0981 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewModel.kt @@ -33,10 +33,10 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.events.model.EventType import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.room.members.roomMemberQueryParams diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt index d736260f104..93ed7fa7194 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/members/RoomMemberListViewState.kt @@ -23,7 +23,7 @@ import com.airbnb.mvrx.Uninitialized import im.vector.app.R import im.vector.app.core.platform.GenericIdArgs import im.vector.app.features.roomprofile.RoomProfileArgs -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt index 59b66603dfc..99701f08c31 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/RoomUploadsMediaFragment.kt @@ -46,11 +46,11 @@ import im.vector.app.features.roomprofile.uploads.RoomUploadsAction import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel import im.vector.app.features.roomprofile.uploads.RoomUploadsViewState +import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl -import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt import javax.inject.Inject class RoomUploadsMediaFragment @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt index 0a5f498b9db..94d29b3078e 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/uploads/media/UploadsMediaController.kt @@ -26,13 +26,13 @@ import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.media.ImageContentRenderer import im.vector.app.features.media.VideoContentRenderer import im.vector.app.features.roomprofile.uploads.RoomUploadsViewState +import org.matrix.android.sdk.api.session.crypto.attachments.toElementToDecrypt import org.matrix.android.sdk.api.session.room.model.message.MessageImageContent import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent import org.matrix.android.sdk.api.session.room.model.message.getFileUrl import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl import org.matrix.android.sdk.api.session.room.uploads.UploadEvent -import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt import javax.inject.Inject class UploadsMediaController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/session/VectorSessionStore.kt b/vector/src/main/java/im/vector/app/features/session/VectorSessionStore.kt index a2f31969795..79183e1808c 100644 --- a/vector/src/main/java/im/vector/app/features/session/VectorSessionStore.kt +++ b/vector/src/main/java/im/vector/app/features/session/VectorSessionStore.kt @@ -22,7 +22,7 @@ import androidx.datastore.preferences.core.stringPreferencesKey import im.vector.app.core.extensions.dataStoreProvider import im.vector.app.features.onboarding.FtueUseCase import kotlinx.coroutines.flow.first -import org.matrix.android.sdk.internal.util.md5 +import org.matrix.android.sdk.api.util.md5 /** * User session scoped storage for: diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt index 74fcc0be5da..195072465bc 100755 --- a/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorPreferences.kt @@ -100,6 +100,7 @@ class VectorPreferences @Inject constructor(private val context: Context) { private const val SETTINGS_ENABLE_CHAT_EFFECTS = "SETTINGS_ENABLE_CHAT_EFFECTS" private const val SETTINGS_SHOW_EMOJI_KEYBOARD = "SETTINGS_SHOW_EMOJI_KEYBOARD" private const val SETTINGS_LABS_ENABLE_LATEX_MATHS = "SETTINGS_LABS_ENABLE_LATEX_MATHS" + const val SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE = "SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE" // Room directory private const val SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS = "SETTINGS_ROOM_DIRECTORY_SHOW_ALL_PUBLIC_ROOMS" @@ -865,6 +866,16 @@ class VectorPreferences @Inject constructor(private val context: Context) { return defaultPrefs.getBoolean(SETTINGS_INTERFACE_BUBBLE_KEY, getDefault(R.bool.settings_interface_bubble_default)) } + /** + * Tells if user should always appear offline or not. + * + * @return true if user should always appear offline + */ + fun userAlwaysAppearsOffline(): Boolean { + return defaultPrefs.getBoolean(SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE, + getDefault(R.bool.settings_presence_user_always_appears_offline_default)) + } + /** * Update the rage shake enabled status. * diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt index 50ef864dbf3..c46a64ad314 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsLabsFragment.kt @@ -17,18 +17,23 @@ package im.vector.app.features.settings import android.os.Bundle +import android.text.method.LinkMovementMethod +import android.widget.TextView import androidx.preference.Preference +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.features.MainActivity import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen -import org.matrix.android.sdk.internal.database.lightweight.LightweightSettingsStorage +import im.vector.app.features.home.room.threads.ThreadsManager +import org.matrix.android.sdk.api.settings.LightweightSettingsStorage import javax.inject.Inject class VectorSettingsLabsFragment @Inject constructor( private val vectorPreferences: VectorPreferences, - private val lightweightSettingsStorage: LightweightSettingsStorage + private val lightweightSettingsStorage: LightweightSettingsStorage, + private val threadsManager: ThreadsManager ) : VectorSettingsBaseFragment() { override var titleRes = R.string.room_settings_labs_pref_title @@ -46,15 +51,51 @@ class VectorSettingsLabsFragment @Inject constructor( } // clear cache - findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { - it.onPreferenceClickListener = Preference.OnPreferenceClickListener { - // We should migrate threads only if threads are disabled - vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled()) - lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) - displayLoadingView() - MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + findPreference(VectorPreferences.SETTINGS_LABS_ENABLE_THREAD_MESSAGES)?.let { vectorPref -> + vectorPref.onPreferenceClickListener = Preference.OnPreferenceClickListener { + onThreadsPreferenceClickedInterceptor(vectorPref) false } } } + + /** + * Intercept the click to display a user friendly dialog when their homeserver do not support threads + */ + private fun onThreadsPreferenceClickedInterceptor(vectorSwitchPreference: VectorSwitchPreference) { + val userEnabledThreads = vectorPreferences.areThreadMessagesEnabled() + if (!session.getHomeServerCapabilities().canUseThreading && userEnabledThreads) { + activity?.let { + MaterialAlertDialogBuilder(it) + .setTitle(R.string.threads_labs_enable_notice_title) + .setMessage(threadsManager.getLabsEnableThreadsMessage()) + .setCancelable(true) + .setNegativeButton(R.string.action_not_now) { _, _ -> + vectorSwitchPreference.isChecked = false + } + .setPositiveButton(R.string.action_try_it_out) { _, _ -> + onThreadsPreferenceClicked() + } + .show() + ?.findViewById(android.R.id.message) + ?.apply { + linksClickable = true + movementMethod = LinkMovementMethod.getInstance() + } + } + } else { + onThreadsPreferenceClicked() + } + } + + /** + * Action when threads preference switch is actually clicked + */ + private fun onThreadsPreferenceClicked() { + // We should migrate threads only if threads are disabled + vectorPreferences.setShouldMigrateThreads(!vectorPreferences.areThreadMessagesEnabled()) + lightweightSettingsStorage.setThreadMessagesEnabled(vectorPreferences.areThreadMessagesEnabled()) + displayLoadingView() + MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + } } diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt index 0c7b1bd7d9e..155234a172a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsPreferencesFragment.kt @@ -21,6 +21,7 @@ import android.content.Context import android.os.Bundle import android.widget.CheckedTextView import androidx.core.view.children +import androidx.lifecycle.lifecycleScope import androidx.preference.Preference import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.BuildConfig @@ -36,6 +37,8 @@ import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.configuration.VectorConfiguration import im.vector.app.features.themes.ThemeUtils +import kotlinx.coroutines.launch +import org.matrix.android.sdk.api.session.presence.model.PresenceEnum import javax.inject.Inject class VectorSettingsPreferencesFragment @Inject constructor( @@ -78,6 +81,17 @@ class VectorSettingsPreferencesFragment @Inject constructor( } } + findPreference(VectorPreferences.SETTINGS_PRESENCE_USER_ALWAYS_APPEARS_OFFLINE)!!.let { pref -> + pref.isChecked = vectorPreferences.userAlwaysAppearsOffline() + pref.setOnPreferenceChangeListener { _, newValue -> + val presenceOfflineModeEnabled = newValue as? Boolean ?: false + lifecycleScope.launch { + session.setMyPresence(if (presenceOfflineModeEnabled) PresenceEnum.OFFLINE else PresenceEnum.ONLINE) + } + true + } + } + findPreference(VectorPreferences.SETTINGS_PREF_SPACE_SHOW_ALL_ROOM_IN_HOME)!!.let { pref -> pref.isChecked = vectorPreferences.prefSpacesShowAllRoomInHome() pref.setOnPreferenceChangeListener { _, _ -> diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt index ef87d908ea8..1581bb4676c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsSecurityPrivacyFragment.kt @@ -73,9 +73,9 @@ import me.gujun.android.span.span import org.matrix.android.sdk.api.MatrixCallback import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable import org.matrix.android.sdk.api.raw.RawService -import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DevicesListResponse +import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DevicesListResponse import javax.inject.Inject class VectorSettingsSecurityPrivacyFragment @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt index 964219ce231..95537a87005 100644 --- a/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/account/deactivation/DeactivateAccountViewModel.kt @@ -31,8 +31,8 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.failure.isInvalidUIAAuth import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import org.matrix.android.sdk.api.util.fromBase64 import timber.log.Timber import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt index 5e691f64b24..0d4c39a230c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/crosssigning/CrossSigningSettingsViewModel.kt @@ -36,11 +36,11 @@ import org.matrix.android.sdk.api.auth.data.LoginFlowTypes import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.crosssigning.isVerified +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.flow.flow -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.crosssigning.isVerified -import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth -import org.matrix.android.sdk.internal.util.awaitCallback import timber.log.Timber import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt index ad8cdb7791a..b0f6261424b 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceItem.kt @@ -31,8 +31,8 @@ import im.vector.app.core.resources.ColorProvider import im.vector.app.core.ui.views.ShieldImageView import im.vector.app.core.utils.DimensionConverter import me.gujun.android.span.span -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo /** * A list item for Device. diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt index 2b8fa4b49a8..8f045344408 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetController.kt @@ -28,7 +28,7 @@ import im.vector.app.core.ui.views.toDrawableRes import im.vector.app.features.crypto.verification.epoxy.bottomSheetVerificationActionItem import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo import timber.log.Timber import javax.inject.Inject diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt index 3a944b5a71f..2573a2f3953 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewModel.kt @@ -27,8 +27,8 @@ import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.flow.map import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.flow.flow -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo class DeviceVerificationInfoBottomSheetViewModel @AssistedInject constructor(@Assisted initialState: DeviceVerificationInfoBottomSheetViewState, val session: Session diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewState.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewState.kt index 32927ca068b..d0c236d119c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewState.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DeviceVerificationInfoBottomSheetViewState.kt @@ -19,8 +19,8 @@ package im.vector.app.features.settings.devices import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo data class DeviceVerificationInfoBottomSheetViewState( val deviceId: String, diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesAction.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesAction.kt index e402982d97d..dd8fca38209 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesAction.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesAction.kt @@ -17,7 +17,7 @@ package im.vector.app.features.settings.devices import im.vector.app.core.platform.VectorViewModelAction -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo sealed class DevicesAction : VectorViewModelAction { object Refresh : DevicesAction() diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt index ab63ad08941..2659ff4966f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesController.kt @@ -32,8 +32,8 @@ import im.vector.app.core.resources.StringProvider import im.vector.app.core.ui.list.genericHeaderItem import im.vector.app.core.utils.DimensionConverter import im.vector.app.features.settings.VectorPreferences -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject class DevicesController @Inject constructor(private val errorFormatter: ErrorFormatter, diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt index 9e1f83582ff..941b33a8ef6 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewEvents.kt @@ -20,8 +20,8 @@ package im.vector.app.features.settings.devices import im.vector.app.core.platform.VectorViewEvents import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo /** * Transient events for Ignored users screen diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt index 76e82e69f68..46a2ba03b16 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/DevicesViewModel.kt @@ -53,17 +53,17 @@ import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.auth.registration.nextUncompletedStage import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.Session +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.CryptoDeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import org.matrix.android.sdk.api.session.crypto.verification.VerificationMethod import org.matrix.android.sdk.api.session.crypto.verification.VerificationService import org.matrix.android.sdk.api.session.crypto.verification.VerificationTransaction import org.matrix.android.sdk.api.session.crypto.verification.VerificationTxState +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import org.matrix.android.sdk.api.util.awaitCallback +import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.flow.flow -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo -import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo -import org.matrix.android.sdk.internal.util.awaitCallback import timber.log.Timber import javax.net.ssl.HttpsURLConnection import kotlin.coroutines.Continuation diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt b/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt index 06ef96daf76..eadf020f7ec 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/TrustUtils.kt @@ -16,8 +16,8 @@ package im.vector.app.features.settings.devices -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel -import org.matrix.android.sdk.internal.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.crosssigning.DeviceTrustLevel +import org.matrix.android.sdk.api.session.crypto.model.RoomEncryptionTrustLevel object TrustUtils { diff --git a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt index 407af191514..e897cdccac2 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devices/VectorSettingsDevicesFragment.kt @@ -39,7 +39,7 @@ import im.vector.app.databinding.FragmentGenericRecyclerBinding import im.vector.app.features.auth.ReAuthActivity import im.vector.app.features.crypto.verification.VerificationBottomSheet import org.matrix.android.sdk.api.auth.data.LoginFlowTypes -import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo +import org.matrix.android.sdk.api.session.crypto.model.DeviceInfo import javax.inject.Inject /** diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt index bce15bbf4bd..740ef3996a4 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataFragment.kt @@ -33,7 +33,7 @@ import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.databinding.FragmentGenericRecyclerBinding import org.billcarsonfr.jsonviewer.JSonViewerDialog import org.matrix.android.sdk.api.session.accountdata.UserAccountDataEvent -import org.matrix.android.sdk.internal.di.MoshiProvider +import org.matrix.android.sdk.api.util.MatrixJsonParser import javax.inject.Inject class AccountDataFragment @Inject constructor( @@ -70,7 +70,7 @@ class AccountDataFragment @Inject constructor( } override fun didTap(data: UserAccountDataEvent) { - val jsonString = MoshiProvider.providesMoshi() + val jsonString = MatrixJsonParser.getMoshi() .adapter(UserAccountDataEvent::class.java) .toJson(data) JSonViewerDialog.newInstance( diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsSerializer.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsSerializer.kt index d18a6c2ba84..30c2efc3ce5 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsSerializer.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingEventsSerializer.kt @@ -18,15 +18,15 @@ package im.vector.app.features.settings.devtools import im.vector.app.core.resources.DateProvider import me.gujun.android.span.span +import org.matrix.android.sdk.api.session.crypto.model.ForwardedRoomKeyContent +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent +import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent -import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent -import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest -import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest import org.threeten.bp.format.DateTimeFormatter class GossipingEventsSerializer { diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt index c1b05cca429..dd016c2bf5f 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/GossipingTrailPagedEpoxyController.kt @@ -26,15 +26,15 @@ import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span +import org.matrix.android.sdk.api.session.crypto.model.ForwardedRoomKeyContent +import org.matrix.android.sdk.api.session.crypto.model.GossipingToDeviceObject +import org.matrix.android.sdk.api.session.crypto.model.RoomKeyShareRequest +import org.matrix.android.sdk.api.session.crypto.model.SecretShareRequest import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.EventType +import org.matrix.android.sdk.api.session.events.model.content.OlmEventContent +import org.matrix.android.sdk.api.session.events.model.content.SecretSendEventContent import org.matrix.android.sdk.api.session.events.model.toModel -import org.matrix.android.sdk.internal.crypto.model.event.OlmEventContent -import org.matrix.android.sdk.internal.crypto.model.event.SecretSendEventContent -import org.matrix.android.sdk.internal.crypto.model.rest.ForwardedRoomKeyContent -import org.matrix.android.sdk.internal.crypto.model.rest.GossipingToDeviceObject -import org.matrix.android.sdk.internal.crypto.model.rest.RoomKeyShareRequest -import org.matrix.android.sdk.internal.crypto.model.rest.SecretShareRequest import javax.inject.Inject class GossipingTrailPagedEpoxyController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt index 4c8bd65c0e2..4653f04f2c1 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/IncomingKeyRequestPagedController.kt @@ -24,7 +24,7 @@ import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest import javax.inject.Inject class IncomingKeyRequestPagedController @Inject constructor( diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt index 197a72cb051..a8045c07e3c 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/KeyRequestListViewModel.kt @@ -32,8 +32,8 @@ import im.vector.app.core.platform.EmptyViewEvents import im.vector.app.core.platform.VectorViewModel import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.internal.crypto.IncomingRoomKeyRequest -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.IncomingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest data class KeyRequestListViewState( val incomingRequests: Async> = Uninitialized, diff --git a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt index 0a52c1a7dd8..b23bd77277e 100644 --- a/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt +++ b/vector/src/main/java/im/vector/app/features/settings/devtools/OutgoingKeyRequestPagedController.kt @@ -22,7 +22,7 @@ import im.vector.app.core.ui.list.GenericItem_ import im.vector.app.core.utils.createUIHandler import im.vector.lib.core.utils.epoxy.charsequence.toEpoxyCharSequence import me.gujun.android.span.span -import org.matrix.android.sdk.internal.crypto.OutgoingRoomKeyRequest +import org.matrix.android.sdk.api.session.crypto.model.OutgoingRoomKeyRequest import javax.inject.Inject class OutgoingKeyRequestPagedController @Inject constructor() : PagedListEpoxyController( diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersAction.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersAction.kt new file mode 100644 index 00000000000..48199e557b1 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersAction.kt @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.ignored + +import im.vector.app.core.platform.VectorViewModelAction + +sealed class IgnoredUsersAction : VectorViewModelAction { + data class UnIgnore(val userId: String) : IgnoredUsersAction() +} diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewEvents.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewEvents.kt index 2b2c3eb49d4..8d597a91899 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewEvents.kt @@ -25,4 +25,5 @@ import im.vector.app.core.platform.VectorViewEvents sealed class IgnoredUsersViewEvents : VectorViewEvents { data class Loading(val message: CharSequence? = null) : IgnoredUsersViewEvents() data class Failure(val throwable: Throwable) : IgnoredUsersViewEvents() + object Success : IgnoredUsersViewEvents() } diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt index b2a7b2cbd15..14f7cd92305 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewModel.kt @@ -16,37 +16,21 @@ package im.vector.app.features.settings.ignored -import com.airbnb.mvrx.Async -import com.airbnb.mvrx.Fail -import com.airbnb.mvrx.Loading -import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksViewModelFactory -import com.airbnb.mvrx.Success -import com.airbnb.mvrx.Uninitialized import dagger.assisted.Assisted import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import im.vector.app.core.di.MavericksAssistedViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.platform.VectorViewModel -import im.vector.app.core.platform.VectorViewModelAction import kotlinx.coroutines.launch import org.matrix.android.sdk.api.session.Session -import org.matrix.android.sdk.api.session.user.model.User import org.matrix.android.sdk.flow.flow -data class IgnoredUsersViewState( - val ignoredUsers: List = emptyList(), - val unIgnoreRequest: Async = Uninitialized -) : MavericksState - -sealed class IgnoredUsersAction : VectorViewModelAction { - data class UnIgnore(val userId: String) : IgnoredUsersAction() -} - -class IgnoredUsersViewModel @AssistedInject constructor(@Assisted initialState: IgnoredUsersViewState, - private val session: Session) : - VectorViewModel(initialState) { +class IgnoredUsersViewModel @AssistedInject constructor( + @Assisted initialState: IgnoredUsersViewState, + private val session: Session +) : VectorViewModel(initialState) { @AssistedFactory interface Factory : MavericksAssistedViewModelFactory { @@ -76,20 +60,16 @@ class IgnoredUsersViewModel @AssistedInject constructor(@Assisted initialState: } private fun handleUnIgnore(action: IgnoredUsersAction.UnIgnore) { - setState { - copy( - unIgnoreRequest = Loading() - ) - } - + setState { copy(isLoading = true) } viewModelScope.launch { - val result = runCatching { session.unIgnoreUserIds(listOf(action.userId)) } - setState { - copy( - unIgnoreRequest = result.fold(::Success, ::Fail) - ) + val viewEvent = try { + session.unIgnoreUserIds(listOf(action.userId)) + IgnoredUsersViewEvents.Success + } catch (throwable: Throwable) { + IgnoredUsersViewEvents.Failure(throwable) } - result.onFailure { _viewEvents.post(IgnoredUsersViewEvents.Failure(it)) } + setState { copy(isLoading = false) } + _viewEvents.post(viewEvent) } } } diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewState.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewState.kt new file mode 100644 index 00000000000..3dc1bfe7955 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/IgnoredUsersViewState.kt @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.settings.ignored + +import com.airbnb.mvrx.MavericksState +import org.matrix.android.sdk.api.session.user.model.User + +data class IgnoredUsersViewState( + val ignoredUsers: List = emptyList(), + val isLoading: Boolean = false +) : MavericksState diff --git a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt index 7128639c812..66fa690b827 100644 --- a/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/ignored/VectorSettingsIgnoredUsersFragment.kt @@ -22,8 +22,6 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isVisible -import com.airbnb.mvrx.Async -import com.airbnb.mvrx.Loading import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -32,6 +30,8 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentGenericRecyclerBinding +import im.vector.app.features.MainActivity +import im.vector.app.features.MainActivityArgs import im.vector.app.features.analytics.plan.MobileScreen import javax.inject.Inject @@ -62,10 +62,16 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( when (it) { is IgnoredUsersViewEvents.Loading -> showLoading(it.message) is IgnoredUsersViewEvents.Failure -> showFailure(it.throwable) + IgnoredUsersViewEvents.Success -> handleSuccess() } } } + private fun handleSuccess() { + // A user has been un-ignored, perform a initial sync + MainActivity.restartApp(requireActivity(), MainActivityArgs(clearCache = true)) + } + override fun onDestroyView() { ignoredUsersController.callback = null views.genericRecyclerView.cleanup() @@ -80,11 +86,12 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( override fun onUserIdClicked(userId: String) { MaterialAlertDialogBuilder(requireActivity()) + .setTitle(R.string.room_participants_action_unignore_title) .setMessage(getString(R.string.settings_unignore_user, userId)) - .setPositiveButton(R.string.yes) { _, _ -> + .setPositiveButton(R.string.unignore) { _, _ -> viewModel.handle(IgnoredUsersAction.UnIgnore(userId)) } - .setNegativeButton(R.string.no, null) + .setNegativeButton(R.string.action_cancel, null) .show() } @@ -94,14 +101,6 @@ class VectorSettingsIgnoredUsersFragment @Inject constructor( override fun invalidate() = withState(viewModel) { state -> ignoredUsersController.update(state) - - handleUnIgnoreRequestStatus(state.unIgnoreRequest) - } - - private fun handleUnIgnoreRequestStatus(unIgnoreRequest: Async) { - views.waitingView.root.isVisible = when (unIgnoreRequest) { - is Loading -> true - else -> false - } + views.waitingView.root.isVisible = state.isLoading } } diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt index d363d5d2f3a..79104433ee4 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt @@ -39,6 +39,7 @@ import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.core.pushers.PushersManager import im.vector.app.core.services.GuardServiceStarter +import im.vector.app.core.utils.combineLatest import im.vector.app.core.utils.isIgnoringBatteryOptimizations import im.vector.app.core.utils.requestDisablingBatteryOptimization import im.vector.app.features.analytics.plan.MobileScreen @@ -57,7 +58,6 @@ import org.matrix.android.sdk.api.pushrules.RuleKind import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.pushers.Pusher -import org.matrix.android.sdk.internal.extensions.combineLatest import javax.inject.Inject // Referenced in vector_settings_preferences_root.xml diff --git a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt index acbe893d58c..0af0a8baa5a 100644 --- a/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/settings/threepids/ThreePidsSettingsViewModel.kt @@ -36,9 +36,9 @@ import org.matrix.android.sdk.api.auth.UserPasswordAuth import org.matrix.android.sdk.api.auth.registration.RegistrationFlowResponse import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.identity.ThreePid +import org.matrix.android.sdk.api.session.uia.DefaultBaseAuth +import org.matrix.android.sdk.api.util.fromBase64 import org.matrix.android.sdk.flow.flow -import org.matrix.android.sdk.internal.crypto.crosssigning.fromBase64 -import org.matrix.android.sdk.internal.crypto.model.rest.DefaultBaseAuth import timber.log.Timber import kotlin.coroutines.Continuation import kotlin.coroutines.resume diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt index abe7e8d2a8b..667f895d4d5 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt @@ -16,27 +16,12 @@ package im.vector.app.features.spaces -import android.view.View -import com.airbnb.epoxy.EpoxyAttribute import com.airbnb.epoxy.EpoxyModelClass import im.vector.app.R -import im.vector.app.core.epoxy.ClickListener import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyModel -import im.vector.app.core.epoxy.onClick @EpoxyModelClass(layout = R.layout.item_space_beta_header) abstract class SpaceBetaHeaderItem : VectorEpoxyModel() { - - @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) - var clickAction: ClickListener? = null - - override fun bind(holder: Holder) { - super.bind(holder) - holder.feedBackAction.onClick(clickAction) - } - - class Holder : VectorEpoxyHolder() { - val feedBackAction by bind(R.id.spaceBetaFeedbackAction) - } + class Holder : VectorEpoxyHolder() } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt index fff8475d2af..a239e939ea8 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListViewModel.kt @@ -55,6 +55,7 @@ import org.matrix.android.sdk.api.session.room.RoomSortOrder import org.matrix.android.sdk.api.session.room.accountdata.RoomAccountDataTypes import org.matrix.android.sdk.api.session.room.model.Membership import org.matrix.android.sdk.api.session.room.roomSummaryQueryParams +import org.matrix.android.sdk.api.session.room.spaceSummaryQueryParams import org.matrix.android.sdk.api.session.room.summary.RoomAggregateNotificationCount import org.matrix.android.sdk.api.session.space.SpaceOrderUtils import org.matrix.android.sdk.api.session.space.model.SpaceOrderContent @@ -272,11 +273,9 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa } private fun observeSpaceSummaries() { - val spaceSummaryQueryParams = roomSummaryQueryParams { + val params = spaceSummaryQueryParams { memberships = listOf(Membership.JOIN, Membership.INVITE) displayName = QueryStringValue.IsNotEmpty - excludeType = listOf(/**RoomType.MESSAGING,$*/ - null) } val flowSession = session.flow() @@ -288,7 +287,7 @@ class SpaceListViewModel @AssistedInject constructor(@Assisted initialState: Spa it.getOrNull() }, flowSession - .liveSpaceSummaries(spaceSummaryQueryParams), + .liveSpaceSummaries(params), session .accountDataService() .getLiveRoomAccountDataEvents(setOf(RoomAccountDataTypes.EVENT_TYPE_SPACE_ORDER)) diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt index 95e4405da55..e88af192630 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceSummaryController.kt @@ -109,9 +109,6 @@ class SpaceSummaryController @Inject constructor( val host = this spaceBetaHeaderItem { id("beta_header") - clickAction { - host.callback?.sendFeedBack() - } } // show invites on top diff --git a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt index 9c6b092135b..b03d21e6bd4 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/invite/SpaceInviteBottomSheetViewModel.kt @@ -16,7 +16,6 @@ package im.vector.app.features.spaces.invite -import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MavericksViewModelFactory diff --git a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt index 8d6a3510130..0c4dcbf90f8 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/manage/SpaceAddRoomFragment.kt @@ -38,7 +38,6 @@ import im.vector.app.core.platform.OnBackPressed import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.databinding.FragmentSpaceAddRoomsBinding import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach diff --git a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt index f5832a85479..23a76b4b68e 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/people/SpacePeopleActivity.kt @@ -24,6 +24,7 @@ import androidx.core.view.isVisible import androidx.lifecycle.lifecycleScope import com.airbnb.mvrx.Mavericks import dagger.hilt.android.AndroidEntryPoint +import im.vector.app.R import im.vector.app.core.extensions.hideKeyboard import im.vector.app.core.extensions.replaceFragment import im.vector.app.core.platform.GenericIdArgs @@ -79,7 +80,7 @@ class SpacePeopleActivity : VectorBaseActivity() { is SpacePeopleSharedAction.NavigateToRoom -> navigateToRooms(sharedAction) SpacePeopleSharedAction.HideModalLoading -> hideWaitingView() SpacePeopleSharedAction.ShowModalLoading -> { - showWaitingView() + showWaitingView(getString(R.string.please_wait)) } is SpacePeopleSharedAction.NavigateToInvite -> { ShareSpaceBottomSheet.show(supportFragmentManager, sharedAction.spaceId) diff --git a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt index 8d34ad94d85..149f582c5cd 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/preview/SpacePreviewViewModel.kt @@ -16,7 +16,6 @@ package im.vector.app.features.spaces.preview -import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MavericksViewModelFactory @@ -35,8 +34,8 @@ import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.room.model.RoomType import org.matrix.android.sdk.api.session.room.peeking.PeekResult import org.matrix.android.sdk.api.session.space.JoinSpaceResult -import org.matrix.android.sdk.internal.session.space.peeking.SpacePeekResult -import org.matrix.android.sdk.internal.session.space.peeking.SpaceSubChildPeekResult +import org.matrix.android.sdk.api.session.space.peeking.SpacePeekResult +import org.matrix.android.sdk.api.session.space.peeking.SpaceSubChildPeekResult import timber.log.Timber class SpacePreviewViewModel @AssistedInject constructor( diff --git a/vector/src/main/java/im/vector/app/features/voice/AbstractVoiceRecorder.kt b/vector/src/main/java/im/vector/app/features/voice/AbstractVoiceRecorder.kt index c07dde5aeb9..14bf09c6c40 100644 --- a/vector/src/main/java/im/vector/app/features/voice/AbstractVoiceRecorder.kt +++ b/vector/src/main/java/im/vector/app/features/voice/AbstractVoiceRecorder.kt @@ -21,7 +21,7 @@ import android.media.MediaRecorder import android.net.Uri import android.os.Build import org.matrix.android.sdk.api.session.content.ContentAttachmentData -import org.matrix.android.sdk.internal.util.md5 +import org.matrix.android.sdk.api.util.md5 import java.io.File import java.io.FileOutputStream import java.util.UUID diff --git a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt index cdffbd54115..51e7e6fcb72 100644 --- a/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt +++ b/vector/src/main/java/im/vector/app/features/widgets/WidgetPostAPIHandler.kt @@ -39,8 +39,6 @@ import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.api.session.widgets.WidgetPostAPIMediator import org.matrix.android.sdk.api.util.JsonDict import timber.log.Timber -import java.util.ArrayList -import java.util.HashMap class WidgetPostAPIHandler @AssistedInject constructor(@Assisted private val roomId: String, private val stringProvider: StringProvider, diff --git a/vector/src/main/res/drawable-hdpi/bg_no_location_map.webp b/vector/src/main/res/drawable-hdpi/bg_no_location_map.webp new file mode 100644 index 00000000000..23a45700f0a Binary files /dev/null and b/vector/src/main/res/drawable-hdpi/bg_no_location_map.webp differ diff --git a/vector/src/main/res/drawable-mdpi/bg_no_location_map.webp b/vector/src/main/res/drawable-mdpi/bg_no_location_map.webp new file mode 100644 index 00000000000..a6130fba782 Binary files /dev/null and b/vector/src/main/res/drawable-mdpi/bg_no_location_map.webp differ diff --git a/vector/src/main/res/drawable-xhdpi/bg_no_location_map.webp b/vector/src/main/res/drawable-xhdpi/bg_no_location_map.webp new file mode 100644 index 00000000000..e908191371e Binary files /dev/null and b/vector/src/main/res/drawable-xhdpi/bg_no_location_map.webp differ diff --git a/vector/src/main/res/drawable-xxhdpi/bg_no_location_map.webp b/vector/src/main/res/drawable-xxhdpi/bg_no_location_map.webp new file mode 100644 index 00000000000..e062178367e Binary files /dev/null and b/vector/src/main/res/drawable-xxhdpi/bg_no_location_map.webp differ diff --git a/vector/src/main/res/drawable-xxxhdpi/bg_no_location_map.webp b/vector/src/main/res/drawable-xxxhdpi/bg_no_location_map.webp new file mode 100644 index 00000000000..8b110d33fe1 Binary files /dev/null and b/vector/src/main/res/drawable-xxxhdpi/bg_no_location_map.webp differ diff --git a/vector/src/main/res/drawable/bg_seek_bar.xml b/vector/src/main/res/drawable/bg_seek_bar.xml new file mode 100644 index 00000000000..0a33522dfd3 --- /dev/null +++ b/vector/src/main/res/drawable/bg_seek_bar.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/drawable/ic_choose_server.xml b/vector/src/main/res/drawable/ic_choose_server.xml new file mode 100644 index 00000000000..26c8e752228 --- /dev/null +++ b/vector/src/main/res/drawable/ic_choose_server.xml @@ -0,0 +1,9 @@ + + + diff --git a/vector/src/main/res/drawable/ic_ems_logo.xml b/vector/src/main/res/drawable/ic_ems_logo.xml new file mode 100644 index 00000000000..68c2aeb1904 --- /dev/null +++ b/vector/src/main/res/drawable/ic_ems_logo.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/vector/src/main/res/drawable/ic_feedback.xml b/vector/src/main/res/drawable/ic_feedback.xml deleted file mode 100644 index e774a8ab5c5..00000000000 --- a/vector/src/main/res/drawable/ic_feedback.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/vector/src/main/res/drawable/ic_headphones.xml b/vector/src/main/res/drawable/ic_headphones.xml deleted file mode 100644 index 86f3d8ab7ff..00000000000 --- a/vector/src/main/res/drawable/ic_headphones.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - diff --git a/vector/src/main/res/drawable/ic_privacy_policy.xml b/vector/src/main/res/drawable/ic_privacy_policy.xml new file mode 100644 index 00000000000..08c63ba44b6 --- /dev/null +++ b/vector/src/main/res/drawable/ic_privacy_policy.xml @@ -0,0 +1,10 @@ + + + diff --git a/vector/src/main/res/layout/activity_call_transfer.xml b/vector/src/main/res/layout/activity_call_transfer.xml index c3febc96a7b..6bf334e62d4 100644 --- a/vector/src/main/res/layout/activity_call_transfer.xml +++ b/vector/src/main/res/layout/activity_call_transfer.xml @@ -17,6 +17,7 @@ @@ -86,4 +87,4 @@ layout="@layout/merge_overlay_waiting_view" /> - \ No newline at end of file + diff --git a/vector/src/main/res/layout/fragment_ftue_account_created.xml b/vector/src/main/res/layout/fragment_ftue_account_created.xml index 5b8dddba22a..268a6d95ac8 100644 --- a/vector/src/main/res/layout/fragment_ftue_account_created.xml +++ b/vector/src/main/res/layout/fragment_ftue_account_created.xml @@ -6,12 +6,6 @@ android:layout_height="match_parent" android:background="?colorSecondary"> - - + + diff --git a/vector/src/main/res/layout/fragment_ftue_sign_up_combined.xml b/vector/src/main/res/layout/fragment_ftue_combined_register.xml similarity index 98% rename from vector/src/main/res/layout/fragment_ftue_sign_up_combined.xml rename to vector/src/main/res/layout/fragment_ftue_combined_register.xml index 9602dd02317..9d61780ad05 100644 --- a/vector/src/main/res/layout/fragment_ftue_sign_up_combined.xml +++ b/vector/src/main/res/layout/fragment_ftue_combined_register.xml @@ -109,7 +109,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:text="@string/ftue_auth_create_account_matrix_dot_org_server_name" android:textColor="?vctr_content_primary" app:layout_constraintBottom_toTopOf="@id/selectedServerDescription" app:layout_constraintEnd_toStartOf="@id/editServerButton" @@ -122,7 +121,6 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="12dp" - android:text="@string/ftue_auth_create_account_matrix_dot_org_server_description" android:textColor="?vctr_content_tertiary" app:layout_constraintBottom_toTopOf="@id/serverSelectionSpacing" app:layout_constraintEnd_toStartOf="@id/editServerButton" @@ -139,7 +137,6 @@ android:paddingEnd="12dp" android:text="@string/ftue_auth_create_account_edit_server_selection" android:textAllCaps="true" - android:visibility="gone" app:layout_constraintBottom_toBottomOf="@id/selectedServerDescription" app:layout_constraintEnd_toEndOf="@id/createAccountGutterEnd" app:layout_constraintTop_toTopOf="@id/chooseYourServerHeader" /> @@ -176,6 +173,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:imeOptions="actionNext" + android:nextFocusForward="@id/createAccountPasswordInput" android:inputType="text" android:maxLines="1" /> diff --git a/vector/src/main/res/layout/fragment_ftue_login_captcha.xml b/vector/src/main/res/layout/fragment_ftue_login_captcha.xml new file mode 100644 index 00000000000..d07e8e2b97c --- /dev/null +++ b/vector/src/main/res/layout/fragment_ftue_login_captcha.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/vector/src/main/res/layout/fragment_ftue_login_terms.xml b/vector/src/main/res/layout/fragment_ftue_login_terms.xml new file mode 100644 index 00000000000..c388b963d9e --- /dev/null +++ b/vector/src/main/res/layout/fragment_ftue_login_terms.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + +