diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..26bef415d7
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,901 @@
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+max_line_length = 160
+tab_width = 4
+ij_continuation_indent_size = 4
+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 = false
+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 = true
+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 = true
+ij_kotlin_method_parameters_right_paren_on_new_line = true
+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/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000000..372c275efc
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,33 @@
+name: APK Build
+
+on:
+ pull_request: { }
+ push:
+ branches: [ main, develop ]
+
+# Enrich gradle.properties for CI/CD
+env:
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
+
+jobs:
+ debug:
+ name: Build debug APKs
+ runs-on: ubuntu-latest
+ if: github.ref != 'refs/heads/main'
+ strategy:
+ fail-fast: false
+ # Allow all jobs on develop. Just one per PR.
+ concurrency:
+ group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}', github.sha) || format('build-debug-{0}', github.ref) }}
+ cancel-in-progress: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Assemble debug APK
+ run: ./gradlew assembleDebug $CI_GRADLE_ARG_PROPERTIES
+ - name: Upload debug APKs
+ uses: actions/upload-artifact@v3
+ with:
+ name: elementx-debug
+ path: |
+ app/build/outputs/apk/debug/app-debug.apk
diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml
new file mode 100644
index 0000000000..8752f339bd
--- /dev/null
+++ b/.github/workflows/danger.yml
@@ -0,0 +1,20 @@
+name: Danger CI
+
+on: [pull_request]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ name: Danger
+ steps:
+ - uses: actions/checkout@v3
+ - run: |
+ npm install --save-dev @babel/plugin-transform-flow-strip-types
+ - name: Danger
+ uses: danger/danger-js@11.2.0
+ with:
+ args: "--dangerfile ./tools/danger/dangerfile.js"
+ env:
+ DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
+ # Fallback for forks
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml
new file mode 100644
index 0000000000..6a456254a9
--- /dev/null
+++ b/.github/workflows/dependabot.yml
@@ -0,0 +1,22 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
+
+version: 2
+updates:
+ # Updates for Github Actions used in the repo
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ reviewers:
+ - "vector-im/element-x-android-reviewers"
+ # Updates for Gradle dependencies used in the app
+ - package-ecosystem: "gradle"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ open-pull-requests-limit: 200
+ reviewers:
+ - "vector-im/element-x-android-reviewers"
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
new file mode 100644
index 0000000000..2741638914
--- /dev/null
+++ b/.github/workflows/quality.yml
@@ -0,0 +1,46 @@
+name: Code Quality Checks
+
+on:
+ pull_request: { }
+ push:
+ branches: [ main, develop ]
+
+# Enrich gradle.properties for CI/CD
+env:
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -XX:MaxPermSize=512m -Dkotlin.daemon.jvm.options="-Xmx2g" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
+
+jobs:
+ check:
+ name: Project Check Suite
+ runs-on: ubuntu-latest
+ # Allow all jobs on main and develop. Just one per PR.
+ concurrency:
+ group: ${{ github.ref == 'refs/heads/main' && format('check-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-develop-{0}', github.sha) || format('check-{0}', github.ref) }}
+ cancel-in-progress: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Run code quality check suite
+ run: ./gradlew check $CI_GRADLE_ARG_PROPERTIES
+ - name: Upload reports
+ if: always()
+ uses: actions/upload-artifact@v3
+ with:
+ name: linting-report
+ path: |
+ */build/reports/**/*.*
+ - name: Prepare Danger
+ if: always()
+ run: |
+ npm install --save-dev @babel/core
+ npm install --save-dev @babel/plugin-transform-flow-strip-types
+ yarn add danger-plugin-lint-report --dev
+ - name: Danger lint
+ if: always()
+ uses: danger/danger-js@11.2.0
+ with:
+ args: "--dangerfile ./tools/danger/dangerfile-lint.js"
+ env:
+ DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }}
+ # Fallback for forks
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 0000000000..02e8ab62b2
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,25 @@
+name: Test
+
+on:
+ pull_request: { }
+ push:
+ branches: [ main, develop ]
+
+# Enrich gradle.properties for CI/CD
+env:
+ GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
+ CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
+
+jobs:
+ tests:
+ name: Runs unit tests
+ runs-on: ubuntu-latest
+
+ # Allow all jobs on main and develop. Just one per PR.
+ concurrency:
+ group: ${{ github.ref == 'refs/heads/main' && format('unit-tests-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('unit-tests-develop-{0}', github.sha) || format('unit-tests-{0}', github.ref) }}
+ cancel-in-progress: true
+ steps:
+ - uses: actions/checkout@v3
+ - name: Run tests
+ run: ./gradlew test $CI_GRADLE_ARG_PROPERTIES
diff --git a/.github/workflows/triage-labelled.yml b/.github/workflows/triage-labelled.yml
index 25dcc59e36..de2522c9e3 100644
--- a/.github/workflows/triage-labelled.yml
+++ b/.github/workflows/triage-labelled.yml
@@ -2,7 +2,7 @@ name: Move labelled issues to correct boards and columns
on:
issues:
- types: [labeled]
+ types: [ labeled ]
jobs:
move_element_x_issues:
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000000..74709d9df5
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,125 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000000..79ee123c2b
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index b288e273cf..82cc63ea3b 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,5 @@
# element-x-android-poc
+
Proof Of Concept to run a Matrix client on Android devices using the Matrix Rust Sdk and Jetpack compose.
-The plan is [here](https://github.com/vector-im/element-x-android-poc/issues/1)!
\ No newline at end of file
+The plan is [here](https://github.com/vector-im/element-x-android-poc/issues/1)!
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9e9a761b65..7b26039ea8 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -5,6 +5,7 @@ plugins {
alias(libs.plugins.anvil)
alias(libs.plugins.kapt)
id("com.google.firebase.appdistribution") version "3.0.2"
+ id("org.jetbrains.kotlinx.knit") version "0.4.0"
}
android {
@@ -12,7 +13,7 @@ android {
defaultConfig {
applicationId = "io.element.android.x"
- targetSdk = 33
+ targetSdk = 33 // TODO Use Versions.targetSdk
versionCode = 1
versionName = "1.0"
@@ -81,7 +82,6 @@ android {
appId = "1:912726360885:android:e17435e0beb0303000427c"
}
}
-
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
@@ -111,6 +111,26 @@ android {
}
}
+// Knit
+apply {
+ plugin("kotlinx-knit")
+}
+
+knit {
+ files = fileTree(project.rootDir) {
+ include(
+ "**/*.md",
+ "**/*.kt",
+ "*/*.kts",
+ )
+ exclude(
+ "**/build/**",
+ "*/.gradle/**",
+ "*/towncrier/template.md",
+ "**/CHANGES.md",
+ )
+ }
+}
dependencies {
implementation(project(":libraries:designsystem"))
@@ -134,7 +154,6 @@ dependencies {
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.startup)
implementation(libs.coil)
- implementation(libs.timber)
implementation(libs.mavericks.compose)
implementation(libs.dagger)
@@ -142,4 +161,4 @@ dependencies {
implementation(libs.showkase)
ksp(libs.showkase.processor)
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/element/android/x/Showkase.kt b/app/src/main/java/io/element/android/x/ElementRootModule.kt
similarity index 78%
rename from app/src/main/java/io/element/android/x/Showkase.kt
rename to app/src/main/java/io/element/android/x/ElementRootModule.kt
index 999cc5bc68..ea6e1e7f31 100644
--- a/app/src/main/java/io/element/android/x/Showkase.kt
+++ b/app/src/main/java/io/element/android/x/ElementRootModule.kt
@@ -4,4 +4,4 @@ import com.airbnb.android.showkase.annotation.ShowkaseRoot
import com.airbnb.android.showkase.annotation.ShowkaseRootModule
@ShowkaseRoot
-class ElementRootModule : ShowkaseRootModule
\ No newline at end of file
+class ElementRootModule : ShowkaseRootModule
diff --git a/app/src/main/java/io/element/android/x/ElementXApplication.kt b/app/src/main/java/io/element/android/x/ElementXApplication.kt
index 7526b9e788..fc6c1b8b8c 100644
--- a/app/src/main/java/io/element/android/x/ElementXApplication.kt
+++ b/app/src/main/java/io/element/android/x/ElementXApplication.kt
@@ -30,6 +30,4 @@ class ElementXApplication : Application(), DaggerComponentOwner {
initializeComponent(MavericksInitializer::class.java)
}
}
-
-
}
diff --git a/app/src/main/java/io/element/android/x/MainActivity.kt b/app/src/main/java/io/element/android/x/MainActivity.kt
index 5dbd6e0252..d6af9a459a 100644
--- a/app/src/main/java/io/element/android/x/MainActivity.kt
+++ b/app/src/main/java/io/element/android/x/MainActivity.kt
@@ -19,8 +19,17 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material3.Button
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
@@ -109,7 +118,6 @@ class MainActivity : ComponentActivity() {
OnLifecycleEvent { _, event ->
Timber.v("OnLifecycleEvent: $event")
}
-
}
@Composable
@@ -171,5 +179,4 @@ class MainActivity : ComponentActivity() {
fun MainContentPreview() {
MainContent(startRoute = OnBoardingScreenNavigationDestination)
}
-
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/element/android/x/MainViewModel.kt b/app/src/main/java/io/element/android/x/MainViewModel.kt
index 36a7b176e0..506431e593 100644
--- a/app/src/main/java/io/element/android/x/MainViewModel.kt
+++ b/app/src/main/java/io/element/android/x/MainViewModel.kt
@@ -50,4 +50,4 @@ class MainViewModel @AssistedInject constructor(
matrixClient.startSync()
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/element/android/x/Navigation.kt b/app/src/main/java/io/element/android/x/Navigation.kt
index 30b544256d..3bf0b95d27 100644
--- a/app/src/main/java/io/element/android/x/Navigation.kt
+++ b/app/src/main/java/io/element/android/x/Navigation.kt
@@ -7,7 +7,11 @@ import com.ramcosta.composedestinations.annotation.RootNavGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.popUpTo
import io.element.android.x.core.di.bindings
-import io.element.android.x.destinations.*
+import io.element.android.x.destinations.ChangeServerScreenNavigationDestination
+import io.element.android.x.destinations.LoginScreenNavigationDestination
+import io.element.android.x.destinations.MessagesScreenNavigationDestination
+import io.element.android.x.destinations.OnBoardingScreenNavigationDestination
+import io.element.android.x.destinations.RoomListScreenNavigationDestination
import io.element.android.x.di.AppBindings
import io.element.android.x.features.login.LoginScreen
import io.element.android.x.features.login.changeserver.ChangeServerScreen
@@ -84,6 +88,3 @@ fun RoomListScreenNavigation(navigator: DestinationsNavigator) {
fun MessagesScreenNavigation(roomId: String, navigator: DestinationsNavigator) {
MessagesScreen(roomId = roomId, onBackPressed = navigator::navigateUp)
}
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 07d5da9cbf..0000000000
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
deleted file mode 100644
index 80e60d5f76..0000000000
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml
deleted file mode 100644
index beab31f753..0000000000
--- a/app/src/main/res/values/ic_launcher_background.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
- #000000
-
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 46fb58517a..ab8ea28281 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -7,8 +7,78 @@ plugins {
alias(libs.plugins.anvil) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.kapt) apply false
+ alias(libs.plugins.detekt)
+ alias(libs.plugins.ktlint)
}
tasks.register("clean").configure {
delete(rootProject.buildDir)
- }
\ No newline at end of file
+}
+
+allprojects {
+ // Detekt
+ apply {
+ plugin("io.gitlab.arturbosch.detekt")
+ }
+ detekt {
+ // preconfigure defaults
+ buildUponDefaultConfig = true
+ // activate all available (even unstable) rules.
+ allRules = true
+ // point to your custom config defining rules to run, overwriting default behavior
+ config = files("$rootDir/tools/detekt/detekt.yml")
+ }
+ dependencies {
+ detektPlugins("com.twitter.compose.rules:detekt:0.0.26")
+ }
+
+ // KtLint
+ apply {
+ plugin("org.jlleitschuh.gradle.ktlint")
+ }
+
+ // See https://github.com/JLLeitschuh/ktlint-gradle#configuration
+ configure {
+ // See https://github.com/pinterest/ktlint/releases/
+ // TODO 0.47.1 is available
+ version.set("0.45.1")
+ android.set(true)
+ ignoreFailures.set(false)
+ enableExperimentalRules.set(true)
+ // display the corresponding rule
+ verbose.set(true)
+ reporters {
+ reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.PLAIN)
+ // To have XML report for Danger
+ reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
+ }
+ filter {
+ exclude { element -> element.file.path.contains("$buildDir/generated/") }
+ }
+ disabledRules.set(
+ setOf(
+ // 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",
+ "experimental:annotation",
+ // - Missing newline after "("
+ // - Missing newline before ")"
+ "wrapping",
+ // - Unnecessary trailing comma before ")"
+ "experimental:trailing-comma",
+ // - A block comment in between other elements on the same line is disallowed
+ "experimental:comment-wrapping",
+ // - A KDoc comment after any other element on the same line must be separated by a new line
+ "experimental:kdoc-wrapping",
+ // Ignore error "Redundant curly braces", since we use it to fix false positives, for instance in "elementLogs.${i}.txt"
+ "string-template",
+ )
+ )
+ }
+}
diff --git a/docs/usefulLinks.md b/docs/usefulLinks.md
index 35ae4cf8c8..9c66616944 100644
--- a/docs/usefulLinks.md
+++ b/docs/usefulLinks.md
@@ -1,14 +1,22 @@
-### VersionCatalog
+
+
+ * [VersionCatalog](#versioncatalog)
+ * [Jetpack Compose](#jetpack-compose)
+
+### VersionCatalog
+https://docs.gradle.org/current/userguide/platforms.html
### Jetpack Compose
https://developer.android.com/jetpack/compose/mental-model
-
+https://developer.android.com/jetpack/compose/libraries
+https://developer.android.com/jetpack/compose/modifiers-list
+
https://android.googlesource.com/platform/frameworks/support/+/androidx-main/compose/docs/compose-api-guidelines.md#api-guidelines-for-jetpack-compose
Preview
https://alexzh.com/jetpack-compose-preview/
-https://github.com/airbnb/Showkase
\ No newline at end of file
+https://github.com/airbnb/Showkase
diff --git a/features/login/build.gradle.kts b/features/login/build.gradle.kts
index 2bf855e13a..5717ba632b 100644
--- a/features/login/build.gradle.kts
+++ b/features/login/build.gradle.kts
@@ -23,8 +23,6 @@ dependencies {
implementation(project(":libraries:elementresources"))
implementation(libs.mavericks.compose)
ksp(libs.showkase.processor)
- implementation(libs.timber)
testImplementation(libs.test.junit)
androidTestImplementation(libs.test.junitext)
-
-}
\ No newline at end of file
+}
diff --git a/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt b/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
index ba9eb96b15..ec5ace41e6 100644
--- a/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
+++ b/features/login/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
package io.element.android.x.features.login
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.*
-
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.x.features.login.test", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/features/login/src/main/AndroidManifest.xml b/features/login/src/main/AndroidManifest.xml
index a5918e68ab..e100076157 100644
--- a/features/login/src/main/AndroidManifest.xml
+++ b/features/login/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
index 6736b98e3d..d7fe0de593 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginScreen.kt
@@ -2,7 +2,13 @@
package io.element.android.x.features.login
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
@@ -10,8 +16,21 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Visibility
import androidx.compose.material.icons.filled.VisibilityOff
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material3.Button
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
@@ -56,19 +75,22 @@ fun LoginScreen(
)
}
-
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LoginContent(
state: LoginViewState,
formState: LoginFormState,
+ modifier: Modifier = Modifier,
onChangeServer: () -> Unit = {},
onLoginChanged: (String) -> Unit = {},
onPasswordChanged: (String) -> Unit = {},
onSubmitClicked: () -> Unit = {},
onLoginWithSuccess: (MatrixClient) -> Unit = {},
) {
- Surface(color = MaterialTheme.colorScheme.background) {
+ Surface(
+ modifier = modifier,
+ color = MaterialTheme.colorScheme.background,
+ ) {
Box(
modifier = Modifier
.fillMaxSize()
@@ -96,7 +118,7 @@ fun LoginContent(
)
// Form
Column(
- //modifier = Modifier.weight(1f),
+ // modifier = Modifier.weight(1f),
) {
Box(
modifier = Modifier.fillMaxWidth()
diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
index 3c39a6a139..735289edfc 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewModel.kt
@@ -66,4 +66,4 @@ class LoginViewModel @AssistedInject constructor(
formState.value = formState.value.copy(login = name)
setState { copy(loggedInClient = Uninitialized) }
}
-}
\ No newline at end of file
+}
diff --git a/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
index f4d4820430..e7871dc504 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/LoginViewState.kt
@@ -23,5 +23,4 @@ data class LoginFormState(
companion object {
val Default = LoginFormState("", "")
}
-
-}
\ No newline at end of file
+}
diff --git a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerScreen.kt b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerScreen.kt
index de03fcb868..3918d2f6c5 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerScreen.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerScreen.kt
@@ -3,13 +3,27 @@
package io.element.android.x.features.login.changeserver
import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.defaultMinSize
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
-import androidx.compose.material3.*
+import androidx.compose.material3.Button
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.OutlinedTextField
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
@@ -45,15 +59,18 @@ fun ChangeServerScreen(
)
}
-
@Composable
fun ChangeServerContent(
state: ChangeServerViewState,
+ modifier: Modifier = Modifier,
onChangeServer: (String) -> Unit = {},
onChangeServerSubmit: () -> Unit = {},
onChangeServerSuccess: () -> Unit = {},
) {
- Surface(color = MaterialTheme.colorScheme.background) {
+ Surface(
+ modifier = modifier,
+ color = MaterialTheme.colorScheme.background,
+ ) {
val scrollState = rememberScrollState()
Box(
modifier = Modifier
@@ -67,8 +84,7 @@ fun ChangeServerContent(
state = scrollState,
)
.padding(horizontal = 16.dp)
- )
- {
+ ) {
val isError = state.changeServerAction is Fail
Box(
modifier = Modifier
@@ -101,7 +117,7 @@ fun ChangeServerContent(
)
Text(
text = "A server is a home for all your data.\n" +
- "You choose your server and it’s easy to make one.", // TODO "Learn more.",
+ "You choose your server and it’s easy to make one.", // TODO "Learn more.",
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally)
diff --git a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewModel.kt b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewModel.kt
index f625c2e75b..e4007dcb4b 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewModel.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewModel.kt
@@ -48,4 +48,4 @@ class ChangeServerViewModel @AssistedInject constructor(
}
}
}
-}
\ No newline at end of file
+}
diff --git a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewState.kt b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewState.kt
index 34a7d4aeb8..8e1f907c31 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewState.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/changeserver/ChangeServerViewState.kt
@@ -10,4 +10,4 @@ data class ChangeServerViewState(
val changeServerAction: Async = Uninitialized,
) : MavericksState {
val submitEnabled = homeserver.isNotEmpty() && changeServerAction !is Loading
-}
\ No newline at end of file
+}
diff --git a/features/login/src/main/java/io/element/android/x/features/login/error/ErrorFormatter.kt b/features/login/src/main/java/io/element/android/x/features/login/error/ErrorFormatter.kt
index ab862e085c..6c26a9aff1 100644
--- a/features/login/src/main/java/io/element/android/x/features/login/error/ErrorFormatter.kt
+++ b/features/login/src/main/java/io/element/android/x/features/login/error/ErrorFormatter.kt
@@ -3,8 +3,8 @@ package io.element.android.x.features.login.error
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import io.element.android.x.core.uri.isValidUrl
-import io.element.android.x.features.login.LoginFormState
import io.element.android.x.element.resources.R as ElementR
+import io.element.android.x.features.login.LoginFormState
@Composable
fun loginError(
diff --git a/features/login/src/main/res/drawable/element_logo_green.xml b/features/login/src/main/res/drawable/element_logo_green.xml
deleted file mode 100644
index 6e948c3536..0000000000
--- a/features/login/src/main/res/drawable/element_logo_green.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
diff --git a/features/login/src/main/res/drawable/ic_baseline_dataset_24.xml b/features/login/src/main/res/drawable/ic_baseline_dataset_24.xml
index f1171cb51c..aa885cbf10 100644
--- a/features/login/src/main/res/drawable/ic_baseline_dataset_24.xml
+++ b/features/login/src/main/res/drawable/ic_baseline_dataset_24.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt b/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
index bcc403cdbf..f1768db5bc 100644
--- a/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
+++ b/features/login/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package io.element.android.x.features.login
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/build.gradle.kts b/features/messages/build.gradle.kts
index 3b6c10c717..4735cd6530 100644
--- a/features/messages/build.gradle.kts
+++ b/features/messages/build.gradle.kts
@@ -23,7 +23,6 @@ dependencies {
implementation(project(":libraries:textcomposer"))
implementation(libs.mavericks.compose)
implementation(libs.coil.compose)
- implementation(libs.timber)
implementation(libs.datetime)
implementation(libs.accompanist.flowlayout)
implementation(libs.androidx.recyclerview)
diff --git a/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt b/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt
index 5594e59678..6c7e4fce97 100644
--- a/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt
+++ b/features/messages/src/androidTest/java/io/element/android/x/features/messages/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
package io.element.android.x.features.messages
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.*
-
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.x.features.messages.test", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/AndroidManifest.xml b/features/messages/src/main/AndroidManifest.xml
index a5918e68ab..e100076157 100644
--- a/features/messages/src/main/AndroidManifest.xml
+++ b/features/messages/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateFactory.kt b/features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateFactory.kt
index d52754b3b2..1dfd5712e7 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateFactory.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/MessageTimelineItemStateFactory.kt
@@ -9,12 +9,20 @@ import io.element.android.x.features.messages.model.AggregatedReaction
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
import io.element.android.x.features.messages.model.MessagesItemReactionState
import io.element.android.x.features.messages.model.MessagesTimelineItemState
-import io.element.android.x.features.messages.model.content.*
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemEmoteContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemEncryptedContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemImageContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemNoticeContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
import io.element.android.x.features.messages.util.invalidateLast
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.media.MediaResolver
import io.element.android.x.matrix.room.MatrixRoom
import io.element.android.x.matrix.timeline.MatrixTimelineItem
+import kotlin.system.measureTimeMillis
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -28,7 +36,6 @@ import org.matrix.rustcomponents.sdk.FormattedBody
import org.matrix.rustcomponents.sdk.MessageFormat
import org.matrix.rustcomponents.sdk.MessageType
import timber.log.Timber
-import kotlin.system.measureTimeMillis
class MessageTimelineItemStateFactory(
private val client: MatrixClient,
@@ -83,7 +90,6 @@ class MessageTimelineItemStateFactory(
timelineItemStates.emit(newTimelineItemStates)
}
-
private fun calculateAndApplyDiff(newTimelineItems: List) {
val timeToDiff = measureTimeMillis {
val diffCallback =
@@ -192,7 +198,6 @@ class MessageTimelineItemStateFactory(
htmlDocument = messageType.content.formatted?.toHtmlDocument()
)
else -> MessagesTimelineItemUnknownContent
-
}
}
@@ -232,5 +237,4 @@ class MessageTimelineItemStateFactory(
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
return AvatarData(name, model, size)
}
-
}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt
index 44320e3e70..a5a44e38f5 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesScreen.kt
@@ -6,9 +6,26 @@
package io.element.android.x.features.messages
-import Avatar
import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.BoxScope
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.offset
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.statusBars
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.layout.widthIn
+import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.items
@@ -20,8 +37,24 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowDownward
import androidx.compose.material.rememberModalBottomSheetState
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.FloatingActionButton
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.SnackbarHost
+import androidx.compose.material3.SnackbarHostState
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.derivedStateOf
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.End
import androidx.compose.ui.Alignment.Companion.Start
@@ -41,18 +74,40 @@ import com.airbnb.mvrx.compose.mavericksViewModel
import io.element.android.x.core.compose.LogCompositions
import io.element.android.x.core.compose.PairCombinedPreviewParameter
import io.element.android.x.core.data.StableCharSequence
+import io.element.android.x.designsystem.components.avatar.Avatar
import io.element.android.x.designsystem.components.avatar.AvatarData
-import io.element.android.x.features.messages.components.*
-import io.element.android.x.features.messages.model.*
-import io.element.android.x.features.messages.model.content.*
+import io.element.android.x.features.messages.components.MessageEventBubble
+import io.element.android.x.features.messages.components.MessagesReactionsView
+import io.element.android.x.features.messages.components.MessagesTimelineItemEncryptedView
+import io.element.android.x.features.messages.components.MessagesTimelineItemImageView
+import io.element.android.x.features.messages.components.MessagesTimelineItemRedactedView
+import io.element.android.x.features.messages.components.MessagesTimelineItemTextView
+import io.element.android.x.features.messages.components.MessagesTimelineItemUnknownView
+import io.element.android.x.features.messages.components.TimelineItemActionsScreen
+import io.element.android.x.features.messages.model.AggregatedReaction
+import io.element.android.x.features.messages.model.MessagesItemGroupPosition
+import io.element.android.x.features.messages.model.MessagesItemGroupPositionProvider
+import io.element.android.x.features.messages.model.MessagesItemReactionState
+import io.element.android.x.features.messages.model.MessagesTimelineItemState
+import io.element.android.x.features.messages.model.MessagesViewState
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemContentProvider
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemEncryptedContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemImageContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemRedactedContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
+import io.element.android.x.features.messages.model.content.MessagesTimelineItemUnknownContent
import io.element.android.x.features.messages.textcomposer.MessageComposerViewModel
import io.element.android.x.features.messages.textcomposer.MessageComposerViewState
import io.element.android.x.textcomposer.MessageComposerMode
import io.element.android.x.textcomposer.TextComposer
+import java.lang.Math.random
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.persistentListOf
+import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
import timber.log.Timber
-import java.lang.Math.random
@Composable
fun MessagesScreen(
@@ -61,7 +116,6 @@ fun MessagesScreen(
viewModel: MessagesViewModel = mavericksViewModel(argsFactory = { roomId }),
composerViewModel: MessageComposerViewModel = mavericksViewModel(argsFactory = { roomId })
) {
-
fun onSendMessage(textMessage: String) {
viewModel.sendMessage(textMessage)
composerViewModel.updateText("")
@@ -88,7 +142,7 @@ fun MessagesScreen(
MessagesScreenContent(
roomTitle = roomTitle,
roomAvatar = roomAvatar,
- timelineItems = timelineItems().orEmpty(),
+ timelineItems = timelineItems().orEmpty().toImmutableList(),
hasMoreToLoad = hasMoreToLoad,
onReachedLoadMore = viewModel::loadMore,
onBackPressed = onBackPressed,
@@ -130,7 +184,7 @@ fun MessagesScreen(
fun MessagesScreenContent(
roomTitle: String?,
roomAvatar: AvatarData?,
- timelineItems: List,
+ timelineItems: ImmutableList,
hasMoreToLoad: Boolean,
onReachedLoadMore: () -> Unit,
onBackPressed: () -> Unit,
@@ -146,9 +200,11 @@ fun MessagesScreenContent(
composerCanSendMessage: Boolean,
composerText: StableCharSequence?,
snackbarHostState: SnackbarHostState,
+ modifier: Modifier = Modifier,
) {
LogCompositions(tag = "MessagesScreen", msg = "Content")
Scaffold(
+ modifier = modifier,
contentWindowInsets = WindowInsets.statusBars,
topBar = {
MessagesTopAppBar(
@@ -187,7 +243,7 @@ fun MessagesScreenContent(
@Composable
fun MessagesContent(
- timelineItems: List,
+ timelineItems: ImmutableList,
hasMoreToLoad: Boolean,
onReachedLoadMore: () -> Unit,
onSendMessage: (String) -> Unit,
@@ -203,7 +259,6 @@ fun MessagesContent(
composerText: StableCharSequence?,
modifier: Modifier = Modifier
) {
-
val lazyListState = rememberLazyListState()
Column(
modifier = modifier
@@ -249,9 +304,11 @@ fun MessagesContent(
fun MessagesTopAppBar(
roomTitle: String?,
roomAvatar: AvatarData?,
- onBackPressed: () -> Unit,
+ modifier: Modifier = Modifier,
+ onBackPressed: () -> Unit = {},
) {
TopAppBar(
+ modifier = modifier,
navigationIcon = {
IconButton(onClick = onBackPressed) {
Icon(
@@ -282,7 +339,7 @@ fun MessagesTopAppBar(
@Composable
fun TimelineItems(
lazyListState: LazyListState,
- timelineItems: List,
+ timelineItems: ImmutableList,
highlightedEventId: String?,
modifier: Modifier = Modifier,
hasMoreToLoad: Boolean = false,
@@ -322,7 +379,6 @@ fun TimelineItems(
onLoadMore = onReachedLoadMore
)
}
-
}
private fun MessagesTimelineItemState.key(): String {
@@ -339,7 +395,6 @@ private fun MessagesTimelineItemState.contentType(): Int {
}
}
-
@Composable
fun TimelineItemRow(
timelineItem: MessagesTimelineItemState,
@@ -426,7 +481,6 @@ fun MessageEventRow(
content = messageEvent.content,
modifier = contentModifier
)
- else -> TODO() /* compiler issue ? */
}
}
MessagesReactionsView(
@@ -471,8 +525,8 @@ private fun MessageSenderInformation(
@Composable
internal fun BoxScope.MessagesScrollHelper(
lazyListState: LazyListState,
- timelineItems: List,
- onLoadMore: () -> Unit,
+ timelineItems: ImmutableList,
+ onLoadMore: () -> Unit = {},
) {
val coroutineScope = rememberCoroutineScope()
val firstVisibleItemIndex by remember { derivedStateOf { lazyListState.firstVisibleItemIndex } }
@@ -526,7 +580,6 @@ internal fun BoxScope.MessagesScrollHelper(
Icon(Icons.Default.ArrowDownward, "")
}
}
-
}
@Composable
@@ -543,7 +596,6 @@ internal fun MessagesLoadingMoreIndicator() {
color = MaterialTheme.colorScheme.primary
)
}
-
}
class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
@@ -551,6 +603,7 @@ class MessagesItemGroupPositionToMessagesTimelineItemContentProvider :
MessagesItemGroupPositionProvider() to MessagesTimelineItemContentProvider()
)
+@Suppress("PreviewPublic")
@Preview(showBackground = true)
@Composable
fun TimelineItemsPreview(
@@ -559,7 +612,7 @@ fun TimelineItemsPreview(
) {
TimelineItems(
lazyListState = LazyListState(),
- timelineItems = listOf(
+ timelineItems = persistentListOf(
// 3 items (First Middle Last) with isMine = false
createMessageEvent(
isMine = false,
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesViewModel.kt b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesViewModel.kt
index 0b8fb62529..98165305f1 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/MessagesViewModel.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/MessagesViewModel.kt
@@ -218,4 +218,4 @@ class MessagesViewModel @AssistedInject constructor(
timeline.callback = null
timeline.dispose()
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessageEventBubble.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessageEventBubble.kt
index 47bf5f3674..51d0faf677 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessageEventBubble.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessageEventBubble.kt
@@ -13,7 +13,13 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
-import io.element.android.x.designsystem.*
+import io.element.android.x.designsystem.LocalIsDarkTheme
+import io.element.android.x.designsystem.MessageHighlightDark
+import io.element.android.x.designsystem.MessageHighlightLight
+import io.element.android.x.designsystem.SystemGrey5Dark
+import io.element.android.x.designsystem.SystemGrey5Light
+import io.element.android.x.designsystem.SystemGrey6Dark
+import io.element.android.x.designsystem.SystemGrey6Light
import io.element.android.x.features.messages.model.MessagesItemGroupPosition
private val BUBBLE_RADIUS = 16.dp
@@ -26,9 +32,9 @@ fun MessageEventBubble(
interactionSource: MutableInteractionSource,
isHighlighted: Boolean,
modifier: Modifier = Modifier,
- onClick: () -> Unit,
- onLongClick: () -> Unit,
- content: @Composable () -> Unit,
+ onClick: () -> Unit = {},
+ onLongClick: () -> Unit = {},
+ content: @Composable () -> Unit = {},
) {
fun bubbleShape(): Shape {
return when (groupPosition) {
@@ -102,4 +108,4 @@ fun MessageEventBubble(
shape = bubbleShape,
content = content
)
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesReactionsView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesReactionsView.kt
index 7b62e9d6cb..0802493a67 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesReactionsView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesReactionsView.kt
@@ -24,7 +24,7 @@ fun MessagesReactionsView(
reactionsState: MessagesItemReactionState,
modifier: Modifier = Modifier,
) {
- if(reactionsState.reactions.isEmpty()) return
+ if (reactionsState.reactions.isEmpty()) return
FlowRow(
modifier = modifier,
mainAxisSpacing = 2.dp,
@@ -53,4 +53,4 @@ fun MessagesReactionButton(reaction: AggregatedReaction, modifier: Modifier = Mo
Text(text = reaction.count, color = MaterialTheme.colorScheme.secondary, fontSize = 12.sp)
}
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemActionsSheet.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemActionsSheet.kt
index 3d1b6cede9..b34c65916d 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemActionsSheet.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemActionsSheet.kt
@@ -3,14 +3,28 @@
package io.element.android.x.features.messages.components
import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.imePadding
+import androidx.compose.foundation.layout.navigationBarsPadding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
-import androidx.compose.material.*
-import androidx.compose.runtime.*
+import androidx.compose.material.ExperimentalMaterialApi
+import androidx.compose.material.ListItem
+import androidx.compose.material.LocalContentColor
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.ModalBottomSheetLayout
+import androidx.compose.material.ModalBottomSheetState
+import androidx.compose.material.ModalBottomSheetValue
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.rememberCoroutineScope
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.unit.dp
import com.airbnb.mvrx.compose.collectAsState
import io.element.android.x.designsystem.components.VectorIcon
@@ -21,7 +35,6 @@ import io.element.android.x.features.messages.model.MessagesTimelineItemState
import io.element.android.x.features.messages.model.MessagesViewState
import io.element.android.x.features.messages.model.content.MessagesTimelineItemTextBasedContent
import io.element.android.x.features.messages.textcomposer.MessageComposerViewModel
-import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -63,7 +76,6 @@ fun TimelineItemActionsScreen(
}
}
-
ModalBottomSheetLayout(
modifier = modifier,
sheetState = modalBottomSheetState,
@@ -71,46 +83,47 @@ fun TimelineItemActionsScreen(
SheetContent(
actionsSheetState = itemActionsSheetState(),
onActionClicked = ::onItemActionClicked,
- modifier = Modifier.navigationBarsPadding().imePadding()
+ modifier = Modifier
+ .navigationBarsPadding()
+ .imePadding()
)
}
) {}
-
}
@Composable
private fun SheetContent(
actionsSheetState: MessagesItemActionsSheetState?,
- onActionClicked: (MessagesItemAction, MessagesTimelineItemState.MessageEvent) -> Unit,
- modifier: Modifier = Modifier
+ modifier: Modifier = Modifier,
+ onActionClicked: (MessagesItemAction, MessagesTimelineItemState.MessageEvent) -> Unit = { _, _ -> },
) {
if (actionsSheetState == null || actionsSheetState.actions.isEmpty()) {
// Crashes if sheetContent size is zero
Box(modifier = modifier.size(1.dp))
- return
- }
- LazyColumn(
- modifier = modifier
- .fillMaxWidth()
- ) {
- items(actionsSheetState.actions) {
- ListItem(
- modifier = Modifier.clickable {
- onActionClicked(it, actionsSheetState.targetItem)
- },
- text = {
- Text(
- text = it.title,
- color = if (it.destructive) MaterialTheme.colors.error else Color.Unspecified,
- )
- },
- icon = {
- VectorIcon(
- resourceId = it.icon,
- tint = if (it.destructive) MaterialTheme.colors.error else LocalContentColor.current,
- )
- }
- )
+ } else {
+ LazyColumn(
+ modifier = modifier
+ .fillMaxWidth()
+ ) {
+ items(actionsSheetState.actions) {
+ ListItem(
+ modifier = Modifier.clickable {
+ onActionClicked(it, actionsSheetState.targetItem)
+ },
+ text = {
+ Text(
+ text = it.title,
+ color = if (it.destructive) MaterialTheme.colors.error else Color.Unspecified,
+ )
+ },
+ icon = {
+ VectorIcon(
+ resourceId = it.icon,
+ tint = if (it.destructive) MaterialTheme.colors.error else LocalContentColor.current,
+ )
+ }
+ )
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt
index d2b280657e..cf89c3418a 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemEncryptedView.kt
@@ -17,4 +17,4 @@ fun MessagesTimelineItemEncryptedView(
icon = Icons.Default.Warning,
modifier = modifier
)
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemImageView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemImageView.kt
index eaac062ae2..35836505db 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemImageView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemImageView.kt
@@ -6,7 +6,6 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.heightIn
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
@@ -16,7 +15,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.ColorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import io.element.android.x.features.messages.model.content.MessagesTimelineItemImageContent
@@ -26,9 +24,9 @@ fun MessagesTimelineItemImageView(
content: MessagesTimelineItemImageContent,
modifier: Modifier = Modifier
) {
- val widthPercent = if(content.aspectRatio > 1f){
+ val widthPercent = if (content.aspectRatio > 1f) {
1f
- }else {
+ } else {
0.7f
}
Box(
@@ -37,7 +35,6 @@ fun MessagesTimelineItemImageView(
.aspectRatio(content.aspectRatio),
contentAlignment = Alignment.Center,
) {
-
var isLoading = rememberSaveable(content.imageMeta) { mutableStateOf(true) }
val context = LocalContext.current
val model = ImageRequest.Builder(context)
@@ -52,4 +49,4 @@ fun MessagesTimelineItemImageView(
onSuccess = { isLoading.value = false },
)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt
index dbfe9ccf96..56f5723486 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemInformativeView.kt
@@ -40,4 +40,4 @@ fun MessagesTimelineItemInformativeView(
text = text
)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt
index bc1a4d2d10..f87ef4c18e 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemRedactedView.kt
@@ -17,4 +17,4 @@ fun MessagesTimelineItemRedactedView(
icon = Icons.Default.Delete,
modifier = modifier
)
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt
index 26fd802bc5..3bbc334533 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemTextView.kt
@@ -22,8 +22,8 @@ fun MessagesTimelineItemTextView(
content: MessagesTimelineItemTextBasedContent,
interactionSource: MutableInteractionSource,
modifier: Modifier = Modifier,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val htmlDocument = content.htmlDocument
if (htmlDocument != null) {
@@ -74,4 +74,4 @@ private fun String.linkify(
end = end
)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt
index 2c9344e02d..9445103c5f 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/MessagesTimelineItemUnknownView.kt
@@ -17,4 +17,4 @@ fun MessagesTimelineItemUnknownView(
icon = Icons.Default.Info,
modifier = modifier
)
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/components/html/HtmlDocument.kt b/features/messages/src/main/java/io/element/android/x/features/messages/components/html/HtmlDocument.kt
index e71769b532..388435c390 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/components/html/HtmlDocument.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/components/html/HtmlDocument.kt
@@ -9,17 +9,25 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.foundation.text.appendInlineContent
-import androidx.compose.material3.*
+import androidx.compose.material3.ColorScheme
+import androidx.compose.material3.LocalTextStyle
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.text.*
+import androidx.compose.ui.text.AnnotatedString
+import androidx.compose.ui.text.SpanStyle
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
+import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.flowlayout.FlowRow
@@ -27,6 +35,7 @@ import io.element.android.x.designsystem.LinkColor
import io.element.android.x.designsystem.components.ClickableLinkText
import io.element.android.x.matrix.permalink.PermalinkData
import io.element.android.x.matrix.permalink.PermalinkParser
+import kotlinx.collections.immutable.persistentMapOf
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.nodes.Node
@@ -38,34 +47,33 @@ private const val chipId = "chip"
fun HtmlDocument(
document: Document,
interactionSource: MutableInteractionSource,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
HtmlBody(
body = document.body(),
+ interactionSource = interactionSource,
modifier = modifier,
onTextClicked = onTextClicked,
onTextLongClicked = onTextLongClicked,
- interactionSource = interactionSource
)
}
@Composable
private fun HtmlBody(
body: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
-
@Composable
fun NodesFlowRode(
nodes: Iterator,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) = FlowRow(
mainAxisSpacing = 2.dp,
crossAxisSpacing = 8.dp,
@@ -106,9 +114,9 @@ private fun HtmlBody(
while (nodesIterator.hasNext()) {
NodesFlowRode(
nodes = nodesIterator,
+ interactionSource = interactionSource,
onTextClicked = onTextClicked,
onTextLongClicked = onTextLongClicked,
- interactionSource = interactionSource
)
}
}
@@ -125,10 +133,10 @@ private fun Element.isInline(): Boolean {
@Composable
private fun HtmlBlock(
element: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val blockModifier = modifier
.padding(top = 4.dp)
@@ -183,10 +191,10 @@ private fun HtmlBlock(
@Composable
private fun HtmlInline(
element: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit,
- onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
Box(modifier) {
val styledText = buildAnnotatedString {
@@ -202,7 +210,10 @@ private fun HtmlInline(
}
@Composable
-private fun HtmlPreformatted(pre: Element, modifier: Modifier = Modifier) {
+private fun HtmlPreformatted(
+ pre: Element,
+ modifier: Modifier = Modifier
+) {
val isCode = pre.firstElementChild()?.normalName() == "code"
val backgroundColor =
if (isCode) MaterialTheme.colorScheme.codeBackground() else Color.Unspecified
@@ -221,9 +232,10 @@ private fun HtmlPreformatted(pre: Element, modifier: Modifier = Modifier) {
@Composable
private fun HtmlParagraph(
paragraph: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
Box(modifier) {
val styledText = buildAnnotatedString {
@@ -239,9 +251,10 @@ private fun HtmlParagraph(
@Composable
private fun HtmlBlockquote(
blockquote: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val color = MaterialTheme.colorScheme.onBackground
Box(
@@ -268,13 +281,13 @@ private fun HtmlBlockquote(
}
}
-
@Composable
private fun HtmlHeading(
heading: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val style = when (heading.normalName()) {
"h1" -> MaterialTheme.typography.headlineLarge.copy(fontSize = 30.sp)
@@ -304,9 +317,10 @@ private fun HtmlHeading(
@Composable
private fun HtmlMxReply(
mxReply: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val blockquote = mxReply.childNodes().firstOrNull() ?: return
val shape = RoundedCornerShape(12.dp)
@@ -356,9 +370,10 @@ private fun HtmlMxReply(
@Composable
private fun HtmlOrderedList(
orderedList: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
var number = 1
val delimiter = "."
@@ -381,9 +396,10 @@ private fun HtmlOrderedList(
@Composable
private fun HtmlUnorderedList(
unorderedList: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
) {
val marker = "・"
HtmlListItems(
@@ -402,14 +418,14 @@ private fun HtmlUnorderedList(
}
}
-
@Composable
private fun HtmlListItems(
list: Element,
- modifier: Modifier = Modifier,
- onTextClicked: () -> Unit, onTextLongClicked: () -> Unit,
interactionSource: MutableInteractionSource,
- content: @Composable (node: TextNode) -> Unit
+ modifier: Modifier = Modifier,
+ onTextClicked: () -> Unit = {},
+ onTextLongClicked: () -> Unit = {},
+ content: @Composable (node: TextNode) -> Unit = {}
) {
Column(modifier = modifier) {
for (node in list.children()) {
@@ -420,13 +436,12 @@ private fun HtmlListItems(
}
is Element -> HtmlBlock(
element = innerNode,
- modifier = modifier.padding(start = 4.dp),
+ modifier = Modifier.padding(start = 4.dp),
onTextClicked = onTextClicked, onTextLongClicked = onTextLongClicked,
interactionSource = interactionSource
)
}
}
-
}
}
}
@@ -439,7 +454,6 @@ private fun AnnotatedString.Builder.appendInlineChildrenElements(
childNodes: List,
colors: ColorScheme
) {
-
for (node in childNodes) {
when (node) {
is TextNode -> {
@@ -452,7 +466,6 @@ private fun AnnotatedString.Builder.appendInlineChildrenElements(
}
}
-
private fun AnnotatedString.Builder.appendInlineElement(element: Element, colors: ColorScheme) {
when (element.normalName()) {
"br" -> {
@@ -490,7 +503,6 @@ private fun AnnotatedString.Builder.appendInlineElement(element: Element, colors
appendInlineChildrenElements(element.childNodes(), colors)
}
}
-
}
private fun AnnotatedString.Builder.appendLink(link: Element) {
@@ -521,13 +533,13 @@ private fun AnnotatedString.Builder.appendLink(link: Element) {
@Composable
private fun HtmlText(
text: AnnotatedString,
+ interactionSource: MutableInteractionSource,
modifier: Modifier = Modifier,
style: TextStyle = LocalTextStyle.current,
- onClick: () -> Unit,
- onLongClick: () -> Unit,
- interactionSource: MutableInteractionSource,
+ onClick: () -> Unit = {},
+ onLongClick: () -> Unit = {},
) {
- val inlineContentMap = emptyMap()
+ val inlineContentMap = persistentMapOf()
ClickableLinkText(
text = text,
linkAnnotationTag = "URL",
@@ -539,4 +551,3 @@ private fun HtmlText(
onLongClick = onLongClick
)
}
-
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/diff/CacheInvalidator.kt b/features/messages/src/main/java/io/element/android/x/features/messages/diff/CacheInvalidator.kt
index 4940ea6046..542bd98b8d 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/diff/CacheInvalidator.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/diff/CacheInvalidator.kt
@@ -37,5 +37,4 @@ internal class CacheInvalidator(private val itemStatesCache: MutableList true
else -> false
}
-
}
internal class MessagesItemGroupPositionProvider : PreviewParameterProvider {
@@ -22,4 +21,4 @@ internal class MessagesItemGroupPositionProvider : PreviewParameterProvider
)
+
@Stable
data class AggregatedReaction(
val key: String,
val count: String,
val isHighlighted: Boolean = false
-)
\ No newline at end of file
+)
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt b/features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt
index e194e9a1a4..fd4bf88f18 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/model/MessagesTimelineItemState.kt
@@ -23,11 +23,5 @@ sealed interface MessagesTimelineItemState {
val showSenderInformation = groupPosition.isNew() && !isMine
val safeSenderName: String = senderDisplayName ?: senderId
-
}
-
-
}
-
-
-
diff --git a/features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt b/features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt
index 57c6edd330..8c758347f8 100644
--- a/features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt
+++ b/features/messages/src/main/java/io/element/android/x/features/messages/model/content/MessagesTimelineItemContent.kt
@@ -2,8 +2,6 @@ package io.element.android.x.features.messages.model.content
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import org.matrix.rustcomponents.sdk.EncryptedMessage
-import org.matrix.rustcomponents.sdk.FormattedBody
-import org.matrix.rustcomponents.sdk.MessageFormat
sealed interface MessagesTimelineItemContent
@@ -28,4 +26,4 @@ class MessagesTimelineItemContentProvider : PreviewParameterProvider MutableList.invalidateLast() {
if (indexOfLast > 0) {
set(indexOfLast - 1, null)
}
-}
\ No newline at end of file
+}
diff --git a/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt b/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt
index d1fddda9b7..01e16c5949 100644
--- a/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt
+++ b/features/messages/src/test/java/io/element/android/x/features/messages/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package io.element.android.x.features.messages
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/features/onboarding/build.gradle.kts b/features/onboarding/build.gradle.kts
index b878aed3c7..a808aa7d8d 100644
--- a/features/onboarding/build.gradle.kts
+++ b/features/onboarding/build.gradle.kts
@@ -12,10 +12,9 @@ dependencies {
implementation(project(":libraries:elementresources"))
implementation(project(":libraries:designsystem"))
implementation(libs.mavericks.compose)
- implementation(libs.timber)
implementation(libs.accompanist.pager)
implementation(libs.accompanist.pagerindicator)
testImplementation(libs.test.junit)
androidTestImplementation(libs.test.junitext)
ksp(libs.showkase.processor)
-}
\ No newline at end of file
+}
diff --git a/features/onboarding/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt b/features/onboarding/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
index ba9eb96b15..ec5ace41e6 100644
--- a/features/onboarding/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
+++ b/features/onboarding/src/androidTest/java/io/element/android/x/features/login/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
package io.element.android.x.features.login
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.*
-
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.x.features.login.test", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/features/onboarding/src/main/AndroidManifest.xml b/features/onboarding/src/main/AndroidManifest.xml
index a5918e68ab..e100076157 100644
--- a/features/onboarding/src/main/AndroidManifest.xml
+++ b/features/onboarding/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingScreen.kt b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingScreen.kt
index 8a1b4bfa39..55d3375a4a 100644
--- a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingScreen.kt
+++ b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingScreen.kt
@@ -3,12 +3,24 @@
package io.element.android.x.features.onboarding
import androidx.compose.foundation.Image
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
-import androidx.compose.runtime.*
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -42,19 +54,20 @@ fun OnBoardingScreen(
)
}
-
@OptIn(ExperimentalPagerApi::class)
@Composable
fun OnBoardingContent(
state: OnBoardingViewState,
- onPageChanged: (Int) -> Unit,
- onSignUp: () -> Unit,
- onSignIn: () -> Unit,
+ modifier: Modifier = Modifier,
+ onPageChanged: (Int) -> Unit = {},
+ onSignUp: () -> Unit = {},
+ onSignIn: () -> Unit = {},
) {
val carrouselState = remember { SplashCarouselStateFactory().create() }
val nbOfPages = carrouselState.items.size
var key by remember { mutableStateOf(false) }
Surface(
+ modifier = modifier,
color = MaterialTheme.colorScheme.background,
) {
Box(
@@ -125,8 +138,11 @@ fun OnBoardingContent(
@Composable
fun OnBoardingPage(
item: SplashCarouselState.Item,
+ modifier: Modifier = Modifier,
) {
- Box {
+ Box(
+ modifier = modifier,
+ ) {
/*
Image(
painterResource(id = item.pageBackground),
@@ -164,4 +180,4 @@ fun OnBoardingPage(
)
}
}
-}
\ No newline at end of file
+}
diff --git a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingViewModel.kt b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingViewModel.kt
index 0749c4a50d..b1f708b126 100644
--- a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingViewModel.kt
+++ b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/OnBoardingViewModel.kt
@@ -12,4 +12,4 @@ class OnBoardingViewModel(initialState: OnBoardingViewState) :
)
}
}
-}
\ No newline at end of file
+}
diff --git a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselState.kt b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselState.kt
index f9b0bb9dfb..e21ccf9058 100644
--- a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselState.kt
+++ b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselState.kt
@@ -20,12 +20,12 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
data class SplashCarouselState(
- val items: List-
+ val items: List
-
) {
data class Item(
- @StringRes val title: Int,
- @StringRes val body: Int,
- @DrawableRes val image: Int,
- @DrawableRes val pageBackground: Int
+ @StringRes val title: Int,
+ @StringRes val body: Int,
+ @DrawableRes val image: Int,
+ @DrawableRes val pageBackground: Int
)
}
diff --git a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselStateFactory.kt b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselStateFactory.kt
index e80f591062..04f605279d 100644
--- a/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselStateFactory.kt
+++ b/features/onboarding/src/main/java/io/element/android/x/features/onboarding/SplashCarouselStateFactory.kt
@@ -3,7 +3,7 @@ package io.element.android.x.features.onboarding
import androidx.annotation.DrawableRes
import io.element.android.x.element.resources.R as ElementR
-class SplashCarouselStateFactory() {
+class SplashCarouselStateFactory {
fun create(): SplashCarouselState {
val lightTheme = true
fun background(@DrawableRes lightDrawable: Int) =
diff --git a/features/onboarding/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt b/features/onboarding/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
index bcc403cdbf..f1768db5bc 100644
--- a/features/onboarding/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
+++ b/features/onboarding/src/test/java/io/element/android/x/features/login/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package io.element.android.x.features.login
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/build.gradle.kts b/features/roomlist/build.gradle.kts
index 6b54bb4811..6eb99fa7a3 100644
--- a/features/roomlist/build.gradle.kts
+++ b/features/roomlist/build.gradle.kts
@@ -20,10 +20,9 @@ dependencies {
implementation(project(":libraries:matrix"))
implementation(project(":libraries:designsystem"))
implementation(libs.mavericks.compose)
- implementation(libs.timber)
implementation(libs.datetime)
implementation(libs.accompanist.placeholder)
testImplementation(libs.test.junit)
androidTestImplementation(libs.test.junitext)
ksp(libs.showkase.processor)
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt b/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt
index 8b9c88c9c3..c16a44bebb 100644
--- a/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt
+++ b/features/roomlist/src/androidTest/java/io/element/android/x/features/roomlist/ExampleInstrumentedTest.kt
@@ -1,13 +1,11 @@
package io.element.android.x.features.roomlist
-import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
-
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.Assert.*
-
/**
* Instrumented test, which will execute on an Android device.
*
@@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("io.element.android.x.features.roomlist.test", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/src/main/AndroidManifest.xml b/features/roomlist/src/main/AndroidManifest.xml
index a5918e68ab..e100076157 100644
--- a/features/roomlist/src/main/AndroidManifest.xml
+++ b/features/roomlist/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/LastMessageFormatter.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/LastMessageFormatter.kt
index 4cd35efc15..d06eb20fbc 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/LastMessageFormatter.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/LastMessageFormatter.kt
@@ -2,12 +2,18 @@ package io.element.android.x.features.roomlist
import android.text.format.DateFormat
import android.text.format.DateUtils
-import kotlinx.datetime.*
-import kotlinx.datetime.TimeZone
import java.time.Period
import java.time.format.DateTimeFormatter
-import java.util.*
+import java.util.Locale
import kotlin.math.absoluteValue
+import kotlinx.datetime.Clock
+import kotlinx.datetime.Instant
+import kotlinx.datetime.LocalDateTime
+import kotlinx.datetime.TimeZone
+import kotlinx.datetime.toInstant
+import kotlinx.datetime.toJavaLocalDate
+import kotlinx.datetime.toJavaLocalDateTime
+import kotlinx.datetime.toLocalDateTime
class LastMessageFormatter(
private val clock: Clock = Clock.System,
@@ -29,7 +35,6 @@ class LastMessageFormatter(
DateTimeFormatter.ofPattern(pattern)
}
-
fun format(timestamp: Long?): String {
if (timestamp == null) return ""
val now: Instant = clock.now()
@@ -77,6 +82,4 @@ class LastMessageFormatter(
DateUtils.FORMAT_SHOW_WEEKDAY
).toString()
}
-
-
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
index 148cfd0ecc..dff4871efe 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt
@@ -36,6 +36,8 @@ import io.element.android.x.features.roomlist.model.RoomListRoomSummary
import io.element.android.x.features.roomlist.model.RoomListViewState
import io.element.android.x.features.roomlist.model.stubbedRoomSummaries
import io.element.android.x.matrix.core.RoomId
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toImmutableList
@Composable
fun RoomListScreen(
@@ -53,7 +55,7 @@ fun RoomListScreen(
val roomSummaries by viewModel.collectAsState(RoomListViewState::rooms)
val matrixUser by viewModel.collectAsState(RoomListViewState::user)
RoomListContent(
- roomSummaries = roomSummaries().orEmpty(),
+ roomSummaries = roomSummaries().orEmpty().toImmutableList(),
matrixUser = matrixUser(),
onRoomClicked = onRoomClicked,
onLogoutClicked = viewModel::logout,
@@ -66,16 +68,16 @@ fun RoomListScreen(
@Composable
fun RoomListContent(
- roomSummaries: List,
+ roomSummaries: ImmutableList,
matrixUser: MatrixUser?,
- onRoomClicked: (RoomId) -> Unit,
filter: String,
- onFilterChanged: (String) -> Unit,
- onLogoutClicked: () -> Unit,
- onScrollOver: (IntRange) -> Unit,
isLoginOut: Boolean,
+ modifier: Modifier = Modifier,
+ onRoomClicked: (RoomId) -> Unit = {},
+ onFilterChanged: (String) -> Unit = {},
+ onLogoutClicked: () -> Unit = {},
+ onScrollOver: (IntRange) -> Unit = {},
) {
-
fun onRoomClicked(room: RoomListRoomSummary) {
onRoomClicked(room.roomId)
}
@@ -104,7 +106,7 @@ fun RoomListContent(
}
Scaffold(
- modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
+ modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = {
RoomListTopBar(
matrixUser = matrixUser,
@@ -133,7 +135,7 @@ fun RoomListContent(
}
)
if (isLoginOut) {
- ProgressDialog("Login out...")
+ ProgressDialog(text = "Login out...")
}
}
@@ -176,4 +178,3 @@ fun PreviewableDarkRoomListContent() {
)
}
}
-
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
index 3eaf231818..5137f83761 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt
@@ -4,17 +4,15 @@ import com.airbnb.mvrx.*
import dagger.assisted.Assisted
import dagger.assisted.AssistedInject
import io.element.android.x.anvilannotations.ContributesViewModel
-import io.element.android.x.core.data.parallelMap
+import io.element.android.x.core.coroutine.parallelMap
import io.element.android.x.core.di.daggerMavericksViewModelFactory
import io.element.android.x.designsystem.components.avatar.AvatarData
import io.element.android.x.designsystem.components.avatar.AvatarSize
-import io.element.android.x.di.AppScope
import io.element.android.x.di.SessionScope
import io.element.android.x.features.roomlist.model.MatrixUser
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
import io.element.android.x.features.roomlist.model.RoomListRoomSummaryPlaceholders
import io.element.android.x.features.roomlist.model.RoomListViewState
-import io.element.android.x.matrix.Matrix
import io.element.android.x.matrix.MatrixClient
import io.element.android.x.matrix.media.MediaResolver
import io.element.android.x.matrix.room.RoomSummary
@@ -112,8 +110,8 @@ class RoomListViewModel @AssistedInject constructor(
copy(
rooms = when {
it is Loading ||
- // Note: this second case will prevent to handle correctly the empty case
- (it is Success && it().isEmpty() && filter.isEmpty()) -> {
+ // Note: this second case will prevent to handle correctly the empty case
+ (it is Success && it().isEmpty() && filter.isEmpty()) -> {
// Show fake placeholders to avoid having empty screen
Loading(RoomListRoomSummaryPlaceholders.createFakeList(size = 16))
}
@@ -158,5 +156,4 @@ class RoomListViewModel @AssistedInject constructor(
.resolve(url, kind = MediaResolver.Kind.Thumbnail(size.value))
return AvatarData(name, model, size)
}
-
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomListTopBar.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomListTopBar.kt
index 95b7744f5c..667357cf73 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomListTopBar.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomListTopBar.kt
@@ -2,7 +2,6 @@
package io.element.android.x.features.roomlist.components
-import Avatar
import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.ContentAlpha
@@ -11,9 +10,23 @@ import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Logout
import androidx.compose.material.icons.filled.Search
-import androidx.compose.material3.*
-import androidx.compose.runtime.*
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.MediumTopAppBar
+import androidx.compose.material3.Text
+import androidx.compose.material3.TextField
+import androidx.compose.material3.TextFieldDefaults
+import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarScrollBehavior
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
@@ -24,6 +37,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import io.element.android.x.core.compose.LogCompositions
import io.element.android.x.core.compose.textFieldState
+import io.element.android.x.designsystem.components.avatar.Avatar
import io.element.android.x.designsystem.components.dialogs.ConfirmationDialog
import io.element.android.x.features.roomlist.model.MatrixUser
@@ -35,7 +49,6 @@ fun RoomListTopBar(
onLogoutClicked: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior
) {
-
LogCompositions(tag = "RoomListScreen", msg = "TopBar")
var searchWidgetStateIsOpened by rememberSaveable { mutableStateOf(false) }
@@ -65,20 +78,20 @@ fun RoomListTopBar(
scrollBehavior = scrollBehavior,
)
}
-
}
@Composable
fun SearchRoomListTopBar(
text: String,
- onFilterChanged: (String) -> Unit,
- onCloseClicked: () -> Unit,
- scrollBehavior: TopAppBarScrollBehavior
+ scrollBehavior: TopAppBarScrollBehavior,
+ modifier: Modifier = Modifier,
+ onFilterChanged: (String) -> Unit = {},
+ onCloseClicked: () -> Unit = {},
) {
var filterState by textFieldState(stateValue = text)
val focusRequester = remember { FocusRequester() }
TopAppBar(
- modifier = Modifier
+ modifier = modifier
.nestedScroll(scrollBehavior.nestedScrollConnection),
title = {
TextField(
@@ -184,10 +197,13 @@ private fun DefaultRoomListTopBar(
)
// Log out confirmation dialog
ConfirmationDialog(
- openDialog,
+ isDisplayed = openDialog.value,
title = "Log out",
content = "Do you confirm you want to log out?",
submitText = "Log out",
onSubmitClicked = onLogoutClicked,
+ onDismiss = {
+ openDialog.value = false
+ }
)
}
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomSummaryRow.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomSummaryRow.kt
index 5cdee76523..a83d2cd067 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomSummaryRow.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/components/RoomSummaryRow.kt
@@ -1,16 +1,23 @@
package io.element.android.x.features.roomlist.components
-import Avatar
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.heightIn
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.Immutable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment.Companion.CenterVertically
@@ -29,17 +36,17 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.google.accompanist.placeholder.material.placeholder
+import io.element.android.x.designsystem.components.avatar.Avatar
import io.element.android.x.features.roomlist.model.RoomListRoomSummary
private val minHeight = 72.dp
@Composable
internal fun RoomSummaryRow(
- modifier: Modifier = Modifier,
room: RoomListRoomSummary,
- onClick: (RoomListRoomSummary) -> Unit
+ modifier: Modifier = Modifier,
+ onClick: (RoomListRoomSummary) -> Unit = {},
) {
-
val clickModifier = if (room.isPlaceholder) {
modifier
} else {
@@ -57,7 +64,6 @@ internal fun RoomSummaryRow(
) {
DefaultRoomSummaryRow(room = room)
}
-
}
@Composable
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummary.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummary.kt
index 98e2200df6..893824756f 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummary.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummary.kt
@@ -13,4 +13,5 @@ data class RoomListRoomSummary(
val timestamp: String? = null,
val lastMessage: CharSequence? = null,
val avatarData: AvatarData = AvatarData(),
- val isPlaceholder: Boolean = false,)
+ val isPlaceholder: Boolean = false,
+)
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt
index 1be8c07b2d..645114507f 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListRoomSummaryPlaceholders.kt
@@ -2,7 +2,6 @@ package io.element.android.x.features.roomlist.model
import io.element.android.x.designsystem.components.avatar.AvatarData
-
object RoomListRoomSummaryPlaceholders {
fun create(id: String): RoomListRoomSummary {
@@ -23,6 +22,4 @@ object RoomListRoomSummaryPlaceholders {
}
}
}
-
}
-
diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/stubbed.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/stubbed.kt
index 4c8844b13b..7813171e45 100644
--- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/stubbed.kt
+++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/stubbed.kt
@@ -1,9 +1,11 @@
package io.element.android.x.features.roomlist.model
import io.element.android.x.designsystem.components.avatar.AvatarData
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.persistentListOf
-internal fun stubbedRoomSummaries(): List {
- return listOf(
+internal fun stubbedRoomSummaries(): ImmutableList {
+ return persistentListOf(
RoomListRoomSummary(
name = "Room",
hasUnread = true,
@@ -22,4 +24,4 @@ internal fun stubbedRoomSummaries(): List {
),
RoomListRoomSummaryPlaceholders.create("roomId2")
)
-}
\ No newline at end of file
+}
diff --git a/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt b/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt
index 39034b2cb2..38bdf65d63 100644
--- a/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt
+++ b/features/roomlist/src/test/java/io/element/android/x/features/roomlist/ExampleUnitTest.kt
@@ -1,9 +1,8 @@
package io.element.android.x.features.roomlist
+import org.junit.Assert.assertEquals
import org.junit.Test
-import org.junit.Assert.*
-
/**
* Example local unit test, which will execute on the development machine (host).
*
@@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
-}
\ No newline at end of file
+}
diff --git a/gradle.properties b/gradle.properties
index c4b415660b..9caae7208e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -21,8 +21,7 @@ kotlin.code.style=official
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
-
# Dummy values for signing secrets / nightly
signing.element.nightly.storePassword=Secret
signing.element.nightly.keyId=Secret
-signing.element.nightly.keyPassword=Secret
\ No newline at end of file
+signing.element.nightly.keyPassword=Secret
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 704c0236ac..6b62ade122 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,3 +1,6 @@
+# This file is referenced in ./plugins/settings.gradle.kts to generate the version catalog.
+# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
+
[versions]
# Project
android_gradle_plugin = "7.3.1"
@@ -39,7 +42,6 @@ test_orchestrator = "1.4.1"
#other
mavericks = "3.0.1"
-timber = "5.0.1"
coil = "2.2.1"
datetime = "0.4.0"
wysiwyg = "0.7.0.1"
@@ -52,6 +54,10 @@ jsoup = "1.15.3"
dagger = "2.43"
anvil = "2.4.2"
+# quality
+detekt = "1.22.0"
+ktlint = "11.0.0"
+
[libraries]
# Project
android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" }
@@ -102,13 +108,12 @@ test_orchestrator = { module = "androidx.test:orchestrator", version.ref = "test
# Others
mavericks_compose = { module = "com.airbnb.android:mavericks-compose", version.ref = "mavericks" }
-timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }
coil = { module = "io.coil-kt:coil", version.ref = "coil" }
coil_compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" }
datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "datetime" }
serialization_json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization_json" }
compose_destinations = { module = "io.github.raamcosta.compose-destinations:animations-core", version.ref = "compose_destinations" }
-compose_destinations_processor = {module = "io.github.raamcosta.compose-destinations:ksp", version.ref = "compose_destinations"}
+compose_destinations_processor = { module = "io.github.raamcosta.compose-destinations:ksp", version.ref = "compose_destinations" }
showkase = { module = "com.airbnb.android:showkase", version.ref = "showkase" }
showkase_processor = { module = "com.airbnb.android:showkase-processor", version.ref = "showkase" }
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
@@ -133,4 +138,6 @@ kotlin_android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin_jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kapt = {id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin"}
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
-anvil = {id = "com.squareup.anvil", version.ref = "anvil"}
\ No newline at end of file
+anvil = {id = "com.squareup.anvil", version.ref = "anvil"}
+detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
+ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
diff --git a/libraries/core/src/main/java/io/element/android/x/core/compose/LogCompositions.kt b/libraries/core/src/main/java/io/element/android/x/core/compose/LogCompositions.kt
index 7ab910b135..16f57ab409 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/compose/LogCompositions.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/compose/LogCompositions.kt
@@ -1,22 +1,21 @@
package io.element.android.x.core.compose
-import android.util.Log
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import io.element.android.x.core.BuildConfig
-
+import timber.log.Timber
// Note the inline function below which ensures that this function is essentially
// copied at the call site to ensure that its logging only recompositions from the
// original call site.
@Composable
-inline fun LogCompositions(tag: String, msg: String) {
+fun LogCompositions(tag: String, msg: String) {
if (BuildConfig.DEBUG) {
val ref = remember { Ref(0) }
SideEffect { ref.value++ }
- Log.d(tag, "Compositions: $msg ${ref.value}")
+ Timber.d(tag, "Compositions: $msg ${ref.value}")
}
}
-class Ref(var value: Int)
\ No newline at end of file
+class Ref(var value: Int)
diff --git a/libraries/core/src/main/java/io/element/android/x/core/compose/OnLifecycleEvent.kt b/libraries/core/src/main/java/io/element/android/x/core/compose/OnLifecycleEvent.kt
index 310e85a061..c022703236 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/compose/OnLifecycleEvent.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/compose/OnLifecycleEvent.kt
@@ -12,7 +12,7 @@ import androidx.lifecycle.LifecycleOwner
fun OnLifecycleEvent(onEvent: (owner: LifecycleOwner, event: Lifecycle.Event) -> Unit) {
val eventHandler = rememberUpdatedState(onEvent)
val lifecycleOwner = rememberUpdatedState(LocalLifecycleOwner.current)
-
+
DisposableEffect(lifecycleOwner.value) {
val lifecycle = lifecycleOwner.value.lifecycle
val observer = LifecycleEventObserver { owner, event ->
@@ -24,4 +24,4 @@ fun OnLifecycleEvent(onEvent: (owner: LifecycleOwner, event: Lifecycle.Event) ->
lifecycle.removeObserver(observer)
}
}
-}
\ No newline at end of file
+}
diff --git a/libraries/core/src/main/java/io/element/android/x/core/compose/Previews.kt b/libraries/core/src/main/java/io/element/android/x/core/compose/PairCombinedPreviewParameter.kt
similarity index 100%
rename from libraries/core/src/main/java/io/element/android/x/core/compose/Previews.kt
rename to libraries/core/src/main/java/io/element/android/x/core/compose/PairCombinedPreviewParameter.kt
diff --git a/libraries/core/src/main/java/io/element/android/x/core/compose/TextFieldLocalState.kt b/libraries/core/src/main/java/io/element/android/x/core/compose/TextFieldLocalState.kt
index 188d99260d..0b3067968c 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/compose/TextFieldLocalState.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/compose/TextFieldLocalState.kt
@@ -5,7 +5,6 @@ import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-
@Composable
public fun textFieldState(stateValue: String): MutableState =
- remember(stateValue) { mutableStateOf(stateValue) }
\ No newline at end of file
+ remember(stateValue) { mutableStateOf(stateValue) }
diff --git a/libraries/core/src/main/java/io/element/android/x/core/coroutine/TimingOperators.kt b/libraries/core/src/main/java/io/element/android/x/core/coroutine/TimingOperators.kt
index 67e187b746..c29cb79d9e 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/coroutine/TimingOperators.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/coroutine/TimingOperators.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.core.data.flow
+package io.element.android.x.core.coroutine
import android.os.SystemClock
import kotlinx.coroutines.CoroutineScope
diff --git a/libraries/core/src/main/java/io/element/android/x/core/coroutine/pmap.kt b/libraries/core/src/main/java/io/element/android/x/core/coroutine/pmap.kt
index 36790dd426..90d2b38984 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/coroutine/pmap.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/coroutine/pmap.kt
@@ -1,4 +1,4 @@
-package io.element.android.x.core.data
+package io.element.android.x.core.coroutine
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
@@ -7,4 +7,4 @@ import kotlinx.coroutines.coroutineScope
// https://jivimberg.io/blog/2018/05/04/parallel-map-in-kotlin/
suspend fun Iterable.parallelMap(f: suspend (A) -> B): List = coroutineScope {
map { async { f(it) } }.awaitAll()
-}
\ No newline at end of file
+}
diff --git a/libraries/core/src/main/java/io/element/android/x/core/data/Try.kt b/libraries/core/src/main/java/io/element/android/x/core/data/Try.kt
index 6c3cfa8599..d6a4148ee1 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/data/Try.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/data/Try.kt
@@ -1,13 +1,13 @@
package io.element.android.x.core.data
-import android.util.Log
+import timber.log.Timber
inline fun tryOrNull(message: String? = null, operation: () -> A): A? {
return try {
operation()
} catch (any: Throwable) {
if (message != null) {
- Log.e("TAG", message, any)
+ Timber.e("TAG", message, any)
}
null
}
diff --git a/libraries/core/src/main/java/io/element/android/x/core/ui/DimensionConverter.kt b/libraries/core/src/main/java/io/element/android/x/core/ui/DimensionConverter.kt
index 7564f77f14..bdca1eefd0 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/ui/DimensionConverter.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/ui/DimensionConverter.kt
@@ -24,18 +24,18 @@ class DimensionConverter(val resources: Resources) {
@Px
fun dpToPx(dp: Int): Int {
return TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP,
- dp.toFloat(),
- resources.displayMetrics
+ TypedValue.COMPLEX_UNIT_DIP,
+ dp.toFloat(),
+ resources.displayMetrics
).toInt()
}
@Px
fun spToPx(sp: Int): Int {
return TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_SP,
- sp.toFloat(),
- resources.displayMetrics
+ TypedValue.COMPLEX_UNIT_SP,
+ sp.toFloat(),
+ resources.displayMetrics
).toInt()
}
diff --git a/libraries/core/src/main/java/io/element/android/x/core/ui/View.kt b/libraries/core/src/main/java/io/element/android/x/core/ui/View.kt
index e9c0542c09..a240a4d10c 100644
--- a/libraries/core/src/main/java/io/element/android/x/core/ui/View.kt
+++ b/libraries/core/src/main/java/io/element/android/x/core/ui/View.kt
@@ -35,9 +35,9 @@ fun View.showKeyboard(andRequestFocus: Boolean = false) {
fun View.setHorizontalPadding(padding: Int) {
setPadding(
- padding,
- paddingTop,
- padding,
- paddingBottom
+ padding,
+ paddingTop,
+ padding,
+ paddingBottom
)
}
diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts
index c132b472c3..2fb20b4f6c 100644
--- a/libraries/designsystem/build.gradle.kts
+++ b/libraries/designsystem/build.gradle.kts
@@ -12,4 +12,4 @@ android {
implementation(libs.accompanist.systemui)
ksp(libs.showkase.processor)
}
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/AndroidManifest.xml b/libraries/designsystem/src/main/AndroidManifest.xml
index a5918e68ab..e100076157 100644
--- a/libraries/designsystem/src/main/AndroidManifest.xml
+++ b/libraries/designsystem/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
-
\ No newline at end of file
+
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
index 0bc41fb0d3..6bf9aaca92 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Color.kt
@@ -5,6 +5,7 @@ import com.airbnb.android.showkase.annotation.ShowkaseColor
@ShowkaseColor(name = "LightGrey", group = "Material Design")
val LightGrey = Color(0x993C3C43)
+
@ShowkaseColor(name = "DarkGrey", group = "Material Design")
val DarkGrey = Color(0x99EBEBF5)
@@ -37,7 +38,8 @@ val Vermilion = Color(0xFFFF5B55)
// TODO Update color
val MessageHighlightLight = Azure
+
// TODO Update color
val MessageHighlightDark = Azure
-val LinkColor = Color(0xFF054F6E)
\ No newline at end of file
+val LinkColor = Color(0xFF054F6E)
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
index 2f757fa11b..2e72ebe4ee 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt
@@ -2,7 +2,11 @@ package io.element.android.x.designsystem
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.*
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
@@ -42,8 +46,9 @@ private val LightColorScheme = lightColorScheme(
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
- */
+ */
)
+@Suppress("CompositionLocalAllowlist")
val LocalIsDarkTheme = compositionLocalOf { error("Not defined") }
@Composable
@@ -81,7 +86,4 @@ fun ElementXTheme(
content = content
)
}
-
}
-
-
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
index 3cfdcf85f3..da25eb21ef 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt
@@ -9,7 +9,6 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.sp
import com.airbnb.android.showkase.annotation.ShowkaseTypography
-
@ShowkaseTypography(name = "Body Large", group = "Element")
val bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
@@ -47,7 +46,7 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
- */
+ */
)
object ElementTextStyles {
@@ -231,6 +230,4 @@ object ElementTextStyles {
textAlign = TextAlign.Center
)
}
-
-
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Icons.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/VectorIcons.kt
similarity index 99%
rename from libraries/designsystem/src/main/java/io/element/android/x/designsystem/Icons.kt
rename to libraries/designsystem/src/main/java/io/element/android/x/designsystem/VectorIcons.kt
index bd1d941e3e..0f6be4989d 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Icons.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/VectorIcons.kt
@@ -8,4 +8,4 @@ object VectorIcons {
val Delete = R.drawable.ic_baseline_delete_outline_24
val Reply = R.drawable.ic_baseline_reply_24
val Edit = R.drawable.ic_baseline_edit_24
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ClickableLinkText.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ClickableLinkText.kt
index 39edb34689..0efdb52771 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ClickableLinkText.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ClickableLinkText.kt
@@ -16,6 +16,8 @@ import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextStyle
+import kotlinx.collections.immutable.ImmutableMap
+import kotlinx.collections.immutable.persistentMapOf
@Composable
fun ClickableLinkText(
@@ -26,7 +28,7 @@ fun ClickableLinkText(
interactionSource: MutableInteractionSource,
modifier: Modifier = Modifier,
style: TextStyle = LocalTextStyle.current,
- inlineContent: Map = mapOf(),
+ inlineContent: ImmutableMap = persistentMapOf(),
) {
val uriHandler = LocalUriHandler.current
val layoutResult = remember { mutableStateOf(null) }
@@ -56,7 +58,6 @@ fun ClickableLinkText(
uriHandler.openUri(linkAnnotations.first().item)
}
}
-
}
}
Text(
@@ -69,4 +70,3 @@ fun ClickableLinkText(
inlineContent = inlineContent
)
}
-
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ProgressDialog.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ProgressDialog.kt
index a01c2eeddc..885fff2a61 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ProgressDialog.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/ProgressDialog.kt
@@ -18,14 +18,18 @@ import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
@Composable
-fun ProgressDialog(text: String? = null, onDismiss: () -> Unit = {}) {
+fun ProgressDialog(
+ modifier: Modifier = Modifier,
+ text: String? = null,
+ onDismiss: () -> Unit = {},
+) {
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(dismissOnBackPress = false, dismissOnClickOutside = false)
) {
Box(
contentAlignment = Alignment.Center,
- modifier = Modifier
+ modifier = modifier
.fillMaxWidth()
.background(
color = MaterialTheme.colorScheme.onBackground,
@@ -52,5 +56,5 @@ fun ProgressDialog(text: String? = null, onDismiss: () -> Unit = {}) {
@Composable
@Preview
fun ProgressDialogPreview() {
- ProgressDialog("test dialog content")
-}
\ No newline at end of file
+ ProgressDialog(text = "test dialog content")
+}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
index 70198103eb..df1939e9af 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorButton.kt
@@ -5,7 +5,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-
@Composable
fun VectorButton(text: String, enabled: Boolean, onClick: () -> Unit, modifier: Modifier = Modifier) {
Button(
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt
deleted file mode 100644
index 53ffa2739a..0000000000
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/VectorTextField.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.element.android.x.designsystem.components
-
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.OutlinedTextField
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-
-
-@OptIn(ExperimentalMaterial3Api::class)
-@Composable
-fun VectorTextField(value: String, onValueChange: (String) -> Unit, isError: Boolean = false) {
- OutlinedTextField(
- value = value,
- onValueChange = onValueChange,
- modifier = Modifier.fillMaxWidth(),
- isError = isError
- )
-}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt
index c5eb17164a..cdd1e4bb5b 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt
@@ -1,4 +1,5 @@
-import android.util.Log
+package io.element.android.x.designsystem.components.avatar
+
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
@@ -16,7 +17,7 @@ import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.element.android.x.designsystem.AvatarGradientEnd
import io.element.android.x.designsystem.AvatarGradientStart
-import io.element.android.x.designsystem.components.avatar.AvatarData
+import timber.log.Timber
@Composable
fun Avatar(avatarData: AvatarData, modifier: Modifier = Modifier) {
@@ -44,7 +45,7 @@ private fun ImageAvatar(
AsyncImage(
model = avatarData.model,
onError = {
- Log.e("TAG", "Error $it\n${it.result}", it.result.throwable)
+ Timber.e("TAG", "Error $it\n${it.result}", it.result.throwable)
},
contentDescription = null,
contentScale = ContentScale.Crop,
@@ -52,7 +53,6 @@ private fun ImageAvatar(
)
}
-
@Composable
private fun InitialsAvatar(
initials: String,
@@ -77,5 +77,3 @@ private fun InitialsAvatar(
)
}
}
-
-
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarData.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarData.kt
index ce1fd06dba..34892867ce 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarData.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarData.kt
@@ -30,5 +30,4 @@ data class AvatarData(
result = 31 * result + size.value
return result
}
-
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarSize.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarSize.kt
index 764b547dca..d7834fd352 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarSize.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/AvatarSize.kt
@@ -8,4 +8,4 @@ enum class AvatarSize(val value: Int) {
BIG(48);
val dp = value.dp
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/dialogs/ConfirmationDialog.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/dialogs/ConfirmationDialog.kt
index 1161fcb5f3..fb43ccd3ce 100644
--- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/dialogs/ConfirmationDialog.kt
+++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/dialogs/ConfirmationDialog.kt
@@ -8,25 +8,24 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.MutableState
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun ConfirmationDialog(
- isDisplayed: MutableState,
+ isDisplayed: Boolean,
title: String,
content: String,
+ modifier: Modifier = Modifier,
submitText: String = "OK",
cancelText: String = "Cancel",
onSubmitClicked: () -> Unit = {},
onDismiss: () -> Unit = {},
) {
- if (!isDisplayed.value) return
+ if (!isDisplayed) return
AlertDialog(
+ modifier = modifier,
onDismissRequest = onDismiss,
title = {
Text(text = title)
@@ -42,11 +41,10 @@ fun ConfirmationDialog(
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
- isDisplayed.value = false
onDismiss()
onSubmitClicked()
- })
- {
+ }
+ ) {
Text(submitText)
}
}
@@ -59,7 +57,6 @@ fun ConfirmationDialog(
Button(
modifier = Modifier.fillMaxWidth(),
onClick = {
- isDisplayed.value = false
onDismiss()
}) {
Text(cancelText)
@@ -73,8 +70,8 @@ fun ConfirmationDialog(
@Preview
fun ConfirmationDialogPreview() {
ConfirmationDialog(
- isDisplayed = remember { mutableStateOf(true) },
+ isDisplayed = true,
title = "Title",
content = "Content",
)
-}
\ No newline at end of file
+}
diff --git a/libraries/designsystem/src/main/res/drawable/ic_baseline_delete_outline_24.xml b/libraries/designsystem/src/main/res/drawable/ic_baseline_delete_outline_24.xml
index ef36649125..33b26af516 100644
--- a/libraries/designsystem/src/main/res/drawable/ic_baseline_delete_outline_24.xml
+++ b/libraries/designsystem/src/main/res/drawable/ic_baseline_delete_outline_24.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/libraries/designsystem/src/main/res/drawable/ic_baseline_edit_24.xml b/libraries/designsystem/src/main/res/drawable/ic_baseline_edit_24.xml
index 1c9bd3e6bd..7aeb747672 100644
--- a/libraries/designsystem/src/main/res/drawable/ic_baseline_edit_24.xml
+++ b/libraries/designsystem/src/main/res/drawable/ic_baseline_edit_24.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml b/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml
index c5fba99883..7555e22d54 100644
--- a/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml
+++ b/libraries/designsystem/src/main/res/drawable/ic_baseline_reply_24.xml
@@ -1,5 +1,11 @@
-
-
+
+
diff --git a/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml b/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml
index 8d3848e661..2927820a2b 100644
--- a/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml
+++ b/libraries/designsystem/src/main/res/drawable/ic_content_arrow_forward.xml
@@ -1,5 +1,11 @@
-
-
+
+
diff --git a/libraries/designsystem/src/main/res/drawable/ic_content_copy.xml b/libraries/designsystem/src/main/res/drawable/ic_content_copy.xml
index bac0f6001a..4b70c6f537 100644
--- a/libraries/designsystem/src/main/res/drawable/ic_content_copy.xml
+++ b/libraries/designsystem/src/main/res/drawable/ic_content_copy.xml
@@ -1,5 +1,10 @@
-
-
+
+
diff --git a/libraries/elementresources/build.gradle.kts b/libraries/elementresources/build.gradle.kts
index bc26e32933..aea3268bf4 100644
--- a/libraries/elementresources/build.gradle.kts
+++ b/libraries/elementresources/build.gradle.kts
@@ -8,4 +8,4 @@ android {
dependencies {
implementation("com.google.android.material:material:1.7.0")
-}
\ No newline at end of file
+}
diff --git a/libraries/elementresources/src/main/AndroidManifest.xml b/libraries/elementresources/src/main/AndroidManifest.xml
index 8bdb7e14b3..e100076157 100644
--- a/libraries/elementresources/src/main/AndroidManifest.xml
+++ b/libraries/elementresources/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/libraries/elementresources/src/main/res/color/button_background_tint_selector.xml b/libraries/elementresources/src/main/res/color/button_background_tint_selector.xml
deleted file mode 100644
index 57135b1eb9..0000000000
--- a/libraries/elementresources/src/main/res/color/button_background_tint_selector.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/color/color_primary_alpha25.xml b/libraries/elementresources/src/main/res/color/color_primary_alpha25.xml
deleted file mode 100644
index 5afa385f3c..0000000000
--- a/libraries/elementresources/src/main/res/color/color_primary_alpha25.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/drawable/bg_send.xml b/libraries/elementresources/src/main/res/drawable/bg_send.xml
deleted file mode 100644
index 06090b3f96..0000000000
--- a/libraries/elementresources/src/main/res/drawable/bg_send.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
- -
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/drawable/ic_attachment.xml b/libraries/elementresources/src/main/res/drawable/ic_attachment.xml
deleted file mode 100644
index 8f2deff482..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_attachment.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_close_round.xml b/libraries/elementresources/src/main/res/drawable/ic_close_round.xml
deleted file mode 100644
index 413a233b56..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_close_round.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_composer_bold.xml b/libraries/elementresources/src/main/res/drawable/ic_composer_bold.xml
deleted file mode 100644
index 3d9a10d16b..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_composer_bold.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_composer_full_screen.xml b/libraries/elementresources/src/main/res/drawable/ic_composer_full_screen.xml
deleted file mode 100644
index 394dc52279..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_composer_full_screen.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_composer_italic.xml b/libraries/elementresources/src/main/res/drawable/ic_composer_italic.xml
deleted file mode 100644
index faa4f89cd4..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_composer_italic.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_composer_strikethrough.xml b/libraries/elementresources/src/main/res/drawable/ic_composer_strikethrough.xml
deleted file mode 100644
index 3970c95381..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_composer_strikethrough.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_composer_underlined.xml b/libraries/elementresources/src/main/res/drawable/ic_composer_underlined.xml
deleted file mode 100644
index fe18d60185..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_composer_underlined.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_edit.xml b/libraries/elementresources/src/main/res/drawable/ic_edit.xml
deleted file mode 100644
index 33214d4246..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_edit.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/ic_send.xml b/libraries/elementresources/src/main/res/drawable/ic_send.xml
deleted file mode 100644
index 9f10eca84a..0000000000
--- a/libraries/elementresources/src/main/res/drawable/ic_send.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
diff --git a/libraries/elementresources/src/main/res/transition/image_preview_transition.xml b/libraries/elementresources/src/main/res/transition/image_preview_transition.xml
deleted file mode 100644
index c1af6d7973..0000000000
--- a/libraries/elementresources/src/main/res/transition/image_preview_transition.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/attrs_room_message_colors.xml b/libraries/elementresources/src/main/res/values/attrs_room_message_colors.xml
deleted file mode 100644
index 68b64c21b0..0000000000
--- a/libraries/elementresources/src/main/res/values/attrs_room_message_colors.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/colors_message_bubble.xml b/libraries/elementresources/src/main/res/values/colors_message_bubble.xml
deleted file mode 100644
index 7ac68574b6..0000000000
--- a/libraries/elementresources/src/main/res/values/colors_message_bubble.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
- #E8EDF4
- #21262C
-
- #E7F8F3
- #133A34
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/style_action_button.xml b/libraries/elementresources/src/main/res/values/style_action_button.xml
deleted file mode 100644
index 0a3c73622f..0000000000
--- a/libraries/elementresources/src/main/res/values/style_action_button.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/style_snackbar.xml b/libraries/elementresources/src/main/res/values/style_snackbar.xml
deleted file mode 100644
index d15f846d8f..0000000000
--- a/libraries/elementresources/src/main/res/values/style_snackbar.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_action_mode.xml b/libraries/elementresources/src/main/res/values/styles_action_mode.xml
deleted file mode 100644
index f6e6079633..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_action_mode.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_alert_dialog.xml b/libraries/elementresources/src/main/res/values/styles_alert_dialog.xml
deleted file mode 100644
index 69abc85c39..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_alert_dialog.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_app_bar_layout.xml b/libraries/elementresources/src/main/res/values/styles_app_bar_layout.xml
deleted file mode 100644
index 973a2c5e4a..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_app_bar_layout.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_bottom_sheet.xml b/libraries/elementresources/src/main/res/values/styles_bottom_sheet.xml
index f6c30040d9..a48071cb71 100644
--- a/libraries/elementresources/src/main/res/values/styles_bottom_sheet.xml
+++ b/libraries/elementresources/src/main/res/values/styles_bottom_sheet.xml
@@ -1,62 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_devices_management.xml b/libraries/elementresources/src/main/res/values/styles_devices_management.xml
deleted file mode 100644
index 6b42b85ffd..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_devices_management.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_edit_text.xml b/libraries/elementresources/src/main/res/values/styles_edit_text.xml
index 94f4d86160..a4458d8e4e 100644
--- a/libraries/elementresources/src/main/res/values/styles_edit_text.xml
+++ b/libraries/elementresources/src/main/res/values/styles_edit_text.xml
@@ -1,16 +1,6 @@
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_jump_to_unread.xml b/libraries/elementresources/src/main/res/values/styles_jump_to_unread.xml
deleted file mode 100644
index 21f0ebd5d4..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_jump_to_unread.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_location.xml b/libraries/elementresources/src/main/res/values/styles_location.xml
deleted file mode 100644
index ee893046ba..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_location.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_login.xml b/libraries/elementresources/src/main/res/values/styles_login.xml
deleted file mode 100644
index ab2cb44c5a..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_login.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_popup.xml b/libraries/elementresources/src/main/res/values/styles_popup.xml
deleted file mode 100644
index 2aad848989..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_popup.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_text_input_layout.xml b/libraries/elementresources/src/main/res/values/styles_text_input_layout.xml
deleted file mode 100644
index 4e7a687a7a..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_text_input_layout.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libraries/elementresources/src/main/res/values/styles_text_view.xml b/libraries/elementresources/src/main/res/values/styles_text_view.xml
deleted file mode 100644
index 0dcaf30f48..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_text_view.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_timeline.xml b/libraries/elementresources/src/main/res/values/styles_timeline.xml
deleted file mode 100644
index 9cae19d6b2..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_timeline.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_toolbar.xml b/libraries/elementresources/src/main/res/values/styles_toolbar.xml
deleted file mode 100644
index 893de92aae..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_toolbar.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/styles_voice_broadcast.xml b/libraries/elementresources/src/main/res/values/styles_voice_broadcast.xml
deleted file mode 100644
index eb85378141..0000000000
--- a/libraries/elementresources/src/main/res/values/styles_voice_broadcast.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/text_appearances.xml b/libraries/elementresources/src/main/res/values/text_appearances.xml
deleted file mode 100644
index 570d26fdfd..0000000000
--- a/libraries/elementresources/src/main/res/values/text_appearances.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/values/theme_light.xml b/libraries/elementresources/src/main/res/values/theme_light.xml
index 1e391e2c85..81839a70c1 100644
--- a/libraries/elementresources/src/main/res/values/theme_light.xml
+++ b/libraries/elementresources/src/main/res/values/theme_light.xml
@@ -26,20 +26,8 @@
- @color/vctr_waiting_background_color_light
- @color/vctr_chat_effect_snow_background_light
- @color/element_background_light
- - @color/vctr_message_bubble_inbound_light
- - @color/vctr_message_bubble_outbound_light
- @color/vctr_badge_color_border_light
-
- - #61708B
- - ?colorError
- - @color/element_content_primary_light
- - #FF61708b
- - @color/palette_element_green
- - @color/element_content_secondary_light
- - #FFEEEEEE
- - #FF000000
-
- @color/vctr_presence_indicator_offline_light
- @color/vctr_presence_indicator_online_light
@@ -67,36 +55,7 @@
- @color/element_background_light
- ?vctr_content_primary
-
- - @style/TextAppearance.Vector.Button
- - @style/TextAppearance.Vector.Caption
-
- - @style/TextAppearance.Vector.Body
-
- - @style/TextAppearance.Vector.Subtitle
- - @style/TextAppearance.Vector.Body
- - @style/TextAppearance.Vector.Body
-
-
- - @style/Widget.Vector.TextView.Body
- - @style/Widget.Vector.Button
- - @style/Widget.Vector.Toolbar
-
- - @style/Widget.Vector.TextInputLayout
- - @style/Widget.Vector.AppBarLayout
- - @style/Widget.Vector.PopupMenu
- - @style/Widget.Vector.SnackBar
- - @style/Widget.Vector.SnackBar.Button
- - @style/Widget.Vector.SnackBar.TextView
- - @style/Widget.Vector.ActionMode
-
- - @style/Theme.Vector.BottomSheetDialog.Light
- - @style/ThemeOverlay.Vector.MaterialAlertDialog
-
- @color/element_link_light
@@ -132,10 +91,6 @@
- true
-
- - @transition/image_preview_transition
- - @transition/image_preview_transition
-
- - @style/Widget.Vector.JumpToUnread.Light
-
- @color/vctr_live_location_light
@@ -166,4 +117,4 @@
- @color/vctr_rich_text_editor_menu_button_background_light
-
\ No newline at end of file
+
diff --git a/libraries/matrix/build.gradle.kts b/libraries/matrix/build.gradle.kts
index 591f5b012d..fa9d9802e1 100644
--- a/libraries/matrix/build.gradle.kts
+++ b/libraries/matrix/build.gradle.kts
@@ -16,9 +16,8 @@ dependencies {
api(project(":libraries:rustsdk"))
implementation(project(":libraries:di"))
implementation(project(":libraries:core"))
- implementation(libs.timber)
implementation("net.java.dev.jna:jna:5.12.1@aar")
implementation(libs.coil.compose)
implementation(libs.androidx.datastore.preferences)
implementation(libs.serialization.json)
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
index 31e13261dc..dd59606a15 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/Matrix.kt
@@ -13,7 +13,7 @@ import io.element.android.x.matrix.util.logError
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.asCoroutineDispatcher
-import kotlinx.coroutines.flow.*
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import org.matrix.rustcomponents.sdk.AuthenticationService
import org.matrix.rustcomponents.sdk.Client
@@ -101,4 +101,4 @@ class Matrix @Inject constructor(
baseDirectory = baseDirectory,
)
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
index 81a0f408f5..db16d9f706 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/MatrixClient.kt
@@ -10,13 +10,19 @@ import io.element.android.x.matrix.room.RoomSummaryDataSource
import io.element.android.x.matrix.room.RustRoomSummaryDataSource
import io.element.android.x.matrix.session.SessionStore
import io.element.android.x.matrix.sync.SlidingSyncObserverProxy
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.*
-import timber.log.Timber
import java.io.Closeable
import java.io.File
import java.util.concurrent.atomic.AtomicBoolean
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.withContext
+import org.matrix.rustcomponents.sdk.Client
+import org.matrix.rustcomponents.sdk.ClientDelegate
+import org.matrix.rustcomponents.sdk.MediaSource
+import org.matrix.rustcomponents.sdk.RequiredState
+import org.matrix.rustcomponents.sdk.SlidingSyncMode
+import org.matrix.rustcomponents.sdk.SlidingSyncViewBuilder
+import org.matrix.rustcomponents.sdk.StoppableSpawn
+import timber.log.Timber
class MatrixClient internal constructor(
private val client: Client,
@@ -60,7 +66,7 @@ class MatrixClient internal constructor(
.slidingSync()
.homeserver("https://slidingsync.lab.element.dev")
.withCommonExtensions()
- //.coldCache("ElementX")
+ // .coldCache("ElementX")
.addView(slidingSyncView)
.build()
@@ -148,6 +154,7 @@ class MatrixClient internal constructor(
}
}
+ @OptIn(ExperimentalUnsignedTypes::class)
suspend fun loadMediaContentForSource(source: MediaSource): Result =
withContext(dispatchers.io) {
runCatching {
@@ -155,6 +162,7 @@ class MatrixClient internal constructor(
}
}
+ @OptIn(ExperimentalUnsignedTypes::class)
suspend fun loadMediaThumbnailForSource(
source: MediaSource,
width: Long,
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt
deleted file mode 100644
index 90aaaa6251..0000000000
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/RoomWrapper.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.element.android.x.matrix
-
-import android.util.Log
-import org.matrix.rustcomponents.sdk.Client
-import org.matrix.rustcomponents.sdk.Room
-
-class RoomWrapper(
- private val client: Client
-) {
- fun getRoom(roomId: String): Room? {
- val rooms = client.rooms()
- Log.d(LOG_TAG, "We have ${rooms.size} rooms")
- return rooms.firstOrNull { it.id() == roomId }
- }
-}
\ No newline at end of file
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/EventId.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/EventId.kt
index ee90c7d1d0..bcc6801a1f 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/EventId.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/EventId.kt
@@ -3,4 +3,4 @@ package io.element.android.x.matrix.core
import java.io.Serializable
@JvmInline
-value class EventId(val value: String) : Serializable
\ No newline at end of file
+value class EventId(val value: String) : Serializable
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/MatrixPatterns.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/MatrixPatterns.kt
index ab516d8ba8..e73cf2b024 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/MatrixPatterns.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/MatrixPatterns.kt
@@ -80,15 +80,15 @@ object MatrixPatterns {
// list of patterns to find some matrix item.
val MATRIX_PATTERNS = listOf(
- PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID,
- PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS,
- PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID,
- PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS,
- PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER,
- PATTERN_CONTAIN_MATRIX_ALIAS,
- PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER,
- PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER,
- PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
+ PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ID,
+ PATTERN_CONTAIN_MATRIX_TO_PERMALINK_ROOM_ALIAS,
+ PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ID,
+ PATTERN_CONTAIN_APP_LINK_PERMALINK_ROOM_ALIAS,
+ PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER,
+ PATTERN_CONTAIN_MATRIX_ALIAS,
+ PATTERN_CONTAIN_MATRIX_ROOM_IDENTIFIER,
+ PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER,
+ PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
)
/**
@@ -129,9 +129,9 @@ object MatrixPatterns {
*/
fun isEventId(str: String?): Boolean {
return str != null &&
- (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER ||
- str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3 ||
- str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
+ (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER ||
+ str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3 ||
+ str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
}
/**
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/RoomId.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/RoomId.kt
index cea9a9e8d6..3369cab78a 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/RoomId.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/RoomId.kt
@@ -3,4 +3,4 @@ package io.element.android.x.matrix.core
import java.io.Serializable
@JvmInline
-value class RoomId(val value: String): Serializable
\ No newline at end of file
+value class RoomId(val value: String) : Serializable
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/UserId.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/UserId.kt
index 3c499f8487..cf34ba13c8 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/core/UserId.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/core/UserId.kt
@@ -3,4 +3,4 @@ package io.element.android.x.matrix.core
import java.io.Serializable
@JvmInline
-value class UserId(val value: String): Serializable
\ No newline at end of file
+value class UserId(val value: String) : Serializable
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaFetcher.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaFetcher.kt
index 442af55bf7..3789fcad42 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaFetcher.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaFetcher.kt
@@ -36,4 +36,4 @@ internal class MediaFetcher(
)
}
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaKeyer.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaKeyer.kt
index 4bc77018fa..03f244cc14 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaKeyer.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaKeyer.kt
@@ -7,4 +7,4 @@ internal class MediaKeyer : Keyer {
override fun key(data: MediaResolver.Meta, options: Options): String? {
return "${data.source.url()}_${data.kind}"
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaResolver.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaResolver.kt
index 949ce02cf4..8a1991298c 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaResolver.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/media/MediaResolver.kt
@@ -24,7 +24,6 @@ interface MediaResolver {
suspend fun resolve(meta: Meta): ByteArray?
}
-
internal class RustMediaResolver(private val client: MatrixClient) : MediaResolver {
override suspend fun resolve(url: String?, kind: MediaResolver.Kind): ByteArray? {
@@ -43,6 +42,4 @@ internal class RustMediaResolver(private val client: MatrixClient) : MediaResolv
)
}.getOrNull()
}
-
-
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/permalink/PermalinkParser.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/permalink/PermalinkParser.kt
index e1f878d331..d23c3d3d4f 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/permalink/PermalinkParser.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/permalink/PermalinkParser.kt
@@ -3,8 +3,8 @@ package io.element.android.x.matrix.permalink
import android.net.Uri
import android.net.UrlQuerySanitizer
import io.element.android.x.matrix.core.MatrixPatterns
-import timber.log.Timber
import java.net.URLDecoder
+import timber.log.Timber
/**
* This class turns a uri to a [PermalinkData].
@@ -43,12 +43,12 @@ object PermalinkParser {
// we are limiting to 2 params
val params = safeFragment
- .split(MatrixPatterns.SEP_REGEX)
- .filter { it.isNotEmpty() }
- .take(2)
+ .split(MatrixPatterns.SEP_REGEX)
+ .filter { it.isNotEmpty() }
+ .take(2)
val decodedParams = params
- .map { URLDecoder.decode(it, "UTF-8") }
+ .map { URLDecoder.decode(it, "UTF-8") }
val identifier = params.getOrNull(0)
val decodedIdentifier = decodedParams.getOrNull(0)
@@ -61,10 +61,10 @@ object PermalinkParser {
}
MatrixPatterns.isRoomAlias(decodedIdentifier) -> {
PermalinkData.RoomLink(
- roomIdOrAlias = decodedIdentifier,
- isRoomAlias = true,
- eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
- viaParameters = viaQueryParameters
+ roomIdOrAlias = decodedIdentifier,
+ isRoomAlias = true,
+ eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
+ viaParameters = viaQueryParameters
)
}
else -> PermalinkData.FallbackLink(uri, MatrixPatterns.isGroupId(identifier))
@@ -83,16 +83,16 @@ object PermalinkParser {
val token = signValidUri.getQueryParameter("token") ?: throw IllegalArgumentException()
val privateKey = signValidUri.getQueryParameter("private_key") ?: throw IllegalArgumentException()
PermalinkData.RoomEmailInviteLink(
- roomId = identifier,
- email = email!!,
- signUrl = signUrl!!,
- roomName = paramList.firstOrNull { it.first == "room_name" }?.second,
- inviterName = paramList.firstOrNull { it.first == "inviter_name" }?.second,
- roomAvatarUrl = paramList.firstOrNull { it.first == "room_avatar_url" }?.second,
- roomType = paramList.firstOrNull { it.first == "room_type" }?.second,
- identityServer = identityServerHost,
- token = token,
- privateKey = privateKey
+ roomId = identifier,
+ email = email!!,
+ signUrl = signUrl!!,
+ roomName = paramList.firstOrNull { it.first == "room_name" }?.second,
+ inviterName = paramList.firstOrNull { it.first == "inviter_name" }?.second,
+ roomAvatarUrl = paramList.firstOrNull { it.first == "room_avatar_url" }?.second,
+ roomType = paramList.firstOrNull { it.first == "room_type" }?.second,
+ identityServer = identityServerHost,
+ token = token,
+ privateKey = privateKey
)
} catch (failure: Throwable) {
Timber.i("## Permalink: Failed to parse permalink $signUrl")
@@ -100,29 +100,29 @@ object PermalinkParser {
}
} else {
PermalinkData.RoomLink(
- roomIdOrAlias = identifier,
- isRoomAlias = false,
- eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
- viaParameters = viaQueryParameters
+ roomIdOrAlias = identifier,
+ isRoomAlias = false,
+ eventId = extraParameter.takeIf { !it.isNullOrEmpty() && MatrixPatterns.isEventId(it) },
+ viaParameters = viaQueryParameters
)
}
}
private fun safeExtractParams(fragment: String) =
- fragment.substringAfter("?").split('&').mapNotNull {
- val splitNameValue = it.split("=")
- if (splitNameValue.size == 2) {
- Pair(splitNameValue[0], URLDecoder.decode(splitNameValue[1], "UTF-8"))
- } else null
- }
+ fragment.substringAfter("?").split('&').mapNotNull {
+ val splitNameValue = it.split("=")
+ if (splitNameValue.size == 2) {
+ Pair(splitNameValue[0], URLDecoder.decode(splitNameValue[1], "UTF-8"))
+ } else null
+ }
private fun String.getViaParameters(): List {
return UrlQuerySanitizer(this)
- .parameterList
- .filter {
- it.mParameter == "via"
- }.map {
- URLDecoder.decode(it.mValue, "UTF-8")
- }
+ .parameterList
+ .filter {
+ it.mParameter == "via"
+ }.map {
+ URLDecoder.decode(it.mValue, "UTF-8")
+ }
}
}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/MatrixRoom.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/MatrixRoom.kt
index 940c3018cf..3bf8b79003 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/MatrixRoom.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/MatrixRoom.kt
@@ -9,7 +9,11 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.*
+import org.matrix.rustcomponents.sdk.Room
+import org.matrix.rustcomponents.sdk.SlidingSyncRoom
+import org.matrix.rustcomponents.sdk.UpdateSummary
+import org.matrix.rustcomponents.sdk.genTransactionId
+import org.matrix.rustcomponents.sdk.messageEventContentFromMarkdown
class MatrixRoom(
private val slidingSyncUpdateFlow: Flow,
@@ -84,7 +88,7 @@ class MatrixRoom(
suspend fun editMessage(originalEventId: String, message: String): Result = withContext(coroutineDispatchers.io) {
val transactionId = genTransactionId()
- val content = messageEventContentFromMarkdown(message)
+ // val content = messageEventContentFromMarkdown(message)
runCatching {
room.edit(/* TODO use content */ message, originalEventId, transactionId)
}
@@ -92,16 +96,16 @@ class MatrixRoom(
suspend fun replyMessage(eventId: String, message: String): Result = withContext(coroutineDispatchers.io) {
val transactionId = genTransactionId()
- val content = messageEventContentFromMarkdown(message)
+ // val content = messageEventContentFromMarkdown(message)
runCatching {
room.sendReply(/* TODO use content */ message, eventId, transactionId)
}
}
- suspend fun redactEvent(eventId: String, reason: String? = null, ) = withContext(coroutineDispatchers.io) {
+ suspend fun redactEvent(eventId: String, reason: String? = null) = withContext(coroutineDispatchers.io) {
val transactionId = genTransactionId()
runCatching {
room.redact(eventId, reason, transactionId)
}
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomListenerFlows.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomListenerFlows.kt
index 691798b6e3..4634e6df12 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomListenerFlows.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomListenerFlows.kt
@@ -9,7 +9,6 @@ import org.matrix.rustcomponents.sdk.Room
import org.matrix.rustcomponents.sdk.TimelineDiff
import org.matrix.rustcomponents.sdk.TimelineListener
-
fun Room.timelineDiff(scope: CoroutineScope): Flow = callbackFlow {
val listener = object : TimelineListener {
override fun onUpdate(update: TimelineDiff) {
@@ -22,6 +21,4 @@ fun Room.timelineDiff(scope: CoroutineScope): Flow = callbackFlow
awaitClose {
removeTimeline()
}
-
}
-
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt
index ff4a01eaf0..580a64e081 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummary.kt
@@ -2,7 +2,6 @@ package io.element.android.x.matrix.room
import io.element.android.x.matrix.core.RoomId
-
sealed interface RoomSummary {
data class Empty(val identifier: String) : RoomSummary
data class Filled(val details: RoomSummaryDetails) : RoomSummary
@@ -13,7 +12,6 @@ sealed interface RoomSummary {
is Filled -> details.roomId.value
}
}
-
}
data class RoomSummaryDetails(
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt
index 91af2c5eca..03e9422157 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDataSource.kt
@@ -3,12 +3,28 @@ package io.element.android.x.matrix.room
import io.element.android.x.core.coroutine.CoroutineDispatchers
import io.element.android.x.matrix.sync.roomListDiff
import io.element.android.x.matrix.sync.state
-import kotlinx.coroutines.*
-import kotlinx.coroutines.flow.*
-import org.matrix.rustcomponents.sdk.*
-import timber.log.Timber
import java.io.Closeable
-import java.util.*
+import java.util.Collections
+import java.util.UUID
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.sample
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import org.matrix.rustcomponents.sdk.RoomListEntry
+import org.matrix.rustcomponents.sdk.SlidingSync
+import org.matrix.rustcomponents.sdk.SlidingSyncState
+import org.matrix.rustcomponents.sdk.SlidingSyncView
+import org.matrix.rustcomponents.sdk.SlidingSyncViewRoomsListDiff
+import org.matrix.rustcomponents.sdk.UpdateSummary
+import timber.log.Timber
interface RoomSummaryDataSource {
fun roomSummaries(): Flow>
@@ -56,7 +72,6 @@ internal class RustRoomSummaryDataSource(
Timber.v("New sliding sync state: $slidingSyncState")
state.value = slidingSyncState
}.launchIn(coroutineScope)
-
}
fun stopSync() {
@@ -67,6 +82,7 @@ internal class RustRoomSummaryDataSource(
coroutineScope.cancel()
}
+ @OptIn(FlowPreview::class)
override fun roomSummaries(): Flow> {
return roomSummaries.sample(50)
}
@@ -95,7 +111,6 @@ internal class RustRoomSummaryDataSource(
}
private fun MutableList.applyDiff(diff: SlidingSyncViewRoomsListDiff) {
-
fun MutableList.fillUntil(untilIndex: Int) {
repeat((size - 1 until untilIndex).count()) {
add(buildEmptyRoomSummary())
@@ -163,4 +178,4 @@ internal class RustRoomSummaryDataSource(
else -> false
}
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDetailsFactory.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDetailsFactory.kt
index 0427987bd5..8f9c4a471b 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDetailsFactory.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/RoomSummaryDetailsFactory.kt
@@ -7,7 +7,7 @@ import org.matrix.rustcomponents.sdk.SlidingSyncRoom
class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFactory = RoomMessageFactory()) {
- fun create(slidingSyncRoom: SlidingSyncRoom, room: Room?): RoomSummaryDetails{
+ fun create(slidingSyncRoom: SlidingSyncRoom, room: Room?): RoomSummaryDetails {
val latestRoomMessage = slidingSyncRoom.latestRoomMessage()?.let {
roomMessageFactory.create(it)
}
@@ -17,14 +17,13 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
else -> "${latestRoomMessage.sender.value}: ${latestRoomMessage.body}"
}
return RoomSummaryDetails(
- roomId = RoomId(slidingSyncRoom.roomId()),
- name = slidingSyncRoom.name() ?: slidingSyncRoom.roomId(),
- isDirect = slidingSyncRoom.isDm() ?: false,
- avatarURLString = room?.avatarUrl(),
- unreadNotificationCount = slidingSyncRoom.unreadNotifications().notificationCount().toInt(),
- lastMessage = computedLastMessage,
- lastMessageTimestamp = latestRoomMessage?.originServerTs
+ roomId = RoomId(slidingSyncRoom.roomId()),
+ name = slidingSyncRoom.name() ?: slidingSyncRoom.roomId(),
+ isDirect = slidingSyncRoom.isDm() ?: false,
+ avatarURLString = room?.avatarUrl(),
+ unreadNotificationCount = slidingSyncRoom.unreadNotifications().notificationCount().toInt(),
+ lastMessage = computedLastMessage,
+ lastMessageTimestamp = latestRoomMessage?.originServerTs
)
}
-
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/message/RoomMessageFactory.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/message/RoomMessageFactory.kt
index 7c82c42472..4bcb86eefb 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/room/message/RoomMessageFactory.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/room/message/RoomMessageFactory.kt
@@ -14,5 +14,4 @@ class RoomMessageFactory {
originServerTs = eventTimelineItem.originServerTs()?.toLong() ?: 0L
)
}
-
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/session/SessionStore.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/session/SessionStore.kt
index a30c5b4ebc..288e181b78 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/session/SessionStore.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/session/SessionStore.kt
@@ -10,7 +10,8 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.serialization.Serializable
-import kotlinx.serialization.*
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.matrix.rustcomponents.sdk.Session
@@ -73,4 +74,4 @@ internal class SessionStore(
suspend fun reset() {
store.edit { it.clear() }
}
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncObserverProxy.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncObserverProxy.kt
index b5365cdf9a..88f8175d86 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncObserverProxy.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncObserverProxy.kt
@@ -11,6 +11,7 @@ import org.matrix.rustcomponents.sdk.UpdateSummary
// Sounds like a reasonable buffer size before it suspends emitting new items.
private const val BUFFER_SIZE = 64
+
class SlidingSyncObserverProxy(
private val coroutineScope: CoroutineScope,
private val coroutineDispatchers: CoroutineDispatchers
@@ -26,5 +27,4 @@ class SlidingSyncObserverProxy(
updateSummaryMutableFlow.emit(summary)
}
}
-
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncViewFlows.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncViewFlows.kt
index 8eaa386390..7cf137c063 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncViewFlows.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/sync/SlidingSyncViewFlows.kt
@@ -1,10 +1,15 @@
package io.element.android.x.matrix.sync
+import io.element.android.x.matrix.util.mxCallbackFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch
-import mxCallbackFlow
-import org.matrix.rustcomponents.sdk.*
+import org.matrix.rustcomponents.sdk.SlidingSyncState
+import org.matrix.rustcomponents.sdk.SlidingSyncView
+import org.matrix.rustcomponents.sdk.SlidingSyncViewRoomListObserver
+import org.matrix.rustcomponents.sdk.SlidingSyncViewRoomsCountObserver
+import org.matrix.rustcomponents.sdk.SlidingSyncViewRoomsListDiff
+import org.matrix.rustcomponents.sdk.SlidingSyncViewStateObserver
fun SlidingSyncView.roomListDiff(scope: CoroutineScope): Flow =
mxCallbackFlow {
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/timeline/MatrixTimeline.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/timeline/MatrixTimeline.kt
index c987716104..41c06c1a9d 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/timeline/MatrixTimeline.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/timeline/MatrixTimeline.kt
@@ -2,15 +2,21 @@ package io.element.android.x.matrix.timeline
import io.element.android.x.core.coroutine.CoroutineDispatchers
import io.element.android.x.matrix.room.MatrixRoom
+import java.util.Collections
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-import org.matrix.rustcomponents.sdk.*
+import org.matrix.rustcomponents.sdk.PaginationOutcome
+import org.matrix.rustcomponents.sdk.Room
+import org.matrix.rustcomponents.sdk.SlidingSyncRoom
+import org.matrix.rustcomponents.sdk.TimelineChange
+import org.matrix.rustcomponents.sdk.TimelineDiff
+import org.matrix.rustcomponents.sdk.TimelineListener
import timber.log.Timber
-import java.util.*
class MatrixTimeline(
private val matrixRoom: MatrixRoom,
@@ -31,7 +37,7 @@ class MatrixTimeline(
private val timelineItems: MutableStateFlow> =
MutableStateFlow(emptyList())
-
+ @OptIn(FlowPreview::class)
fun timelineItems(): Flow> {
return timelineItems.sample(50)
}
@@ -41,7 +47,6 @@ class MatrixTimeline(
return paginationOutcome.value.moreMessages
}
-
private fun MutableList.applyDiff(diff: TimelineDiff) {
when (diff.change()) {
TimelineChange.PUSH -> {
@@ -140,5 +145,4 @@ class MatrixTimeline(
}
}
}
-
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/tracing/TracingConfiguration.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/tracing/TracingConfiguration.kt
index 947bff09f5..de5ae950bb 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/tracing/TracingConfiguration.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/tracing/TracingConfiguration.kt
@@ -9,7 +9,6 @@ data class TracingConfiguration(
targets.map { "${it.key.filter}=${it.value.filter}" }.joinToString(separator = ",")
}"
-
sealed class Target(open val filter: String) {
object Hyper : Target("hyper")
object Sled : Target("sled")
@@ -31,7 +30,6 @@ data class TracingConfiguration(
object Debug : LogLevel("debug")
object Error : LogLevel("error")
}
-
}
fun setupTracing(tracingConfiguration: TracingConfiguration) {
@@ -47,4 +45,4 @@ object TracingConfigurations {
TracingConfiguration.Target.Sled to TracingConfiguration.LogLevel.Warn
)
)
-}
\ No newline at end of file
+}
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/util/CallbackFlow.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/CallbackFlow.kt
index 23bb5f6fbc..842da90e3e 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/util/CallbackFlow.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/CallbackFlow.kt
@@ -1,6 +1,5 @@
-@file:OptIn(ExperimentalCoroutinesApi::class)
+package io.element.android.x.matrix.util
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.ProducerScope
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
@@ -12,4 +11,4 @@ internal fun mxCallbackFlow(block: suspend ProducerScope.() -> StoppableS
awaitClose {
token.cancel()
}
- }
\ No newline at end of file
+ }
diff --git a/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
index c7f4e6ac12..db44533b73 100644
--- a/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
+++ b/libraries/matrix/src/main/java/io/element/android/x/matrix/util/Error.kt
@@ -12,4 +12,4 @@ fun logError(throwable: Throwable) {
Timber.e("Error", throwable)
}
}
-}
\ No newline at end of file
+}
diff --git a/libraries/textcomposer/src/main/AndroidManifest.xml b/libraries/textcomposer/src/main/AndroidManifest.xml
index 8bdb7e14b3..e100076157 100644
--- a/libraries/textcomposer/src/main/AndroidManifest.xml
+++ b/libraries/textcomposer/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/MessageComposerMode.kt b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/MessageComposerMode.kt
index 617eeef499..bf5b556525 100644
--- a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/MessageComposerMode.kt
+++ b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/MessageComposerMode.kt
@@ -34,7 +34,6 @@ sealed interface MessageComposerMode {
override val defaultContent: CharSequence
) : Special(eventId, defaultContent)
-
val relatedEventId: String?
get() = when (this) {
is Normal -> null
@@ -42,7 +41,4 @@ sealed interface MessageComposerMode {
is Quote -> eventId
is Reply -> eventId
}
-
-
}
-
diff --git a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/RichTextComposerLayout.kt b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/RichTextComposerLayout.kt
index 34cc3065b1..eb51388ca3 100644
--- a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/RichTextComposerLayout.kt
+++ b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/RichTextComposerLayout.kt
@@ -45,12 +45,12 @@ import io.element.android.wysiwyg.inputhandlers.models.InlineFormat
import io.element.android.x.core.ui.DimensionConverter
import io.element.android.x.core.ui.hideKeyboard
import io.element.android.x.core.ui.showKeyboard
+import io.element.android.x.element.resources.R as ElementR
import io.element.android.x.textcomposer.databinding.ComposerRichTextLayoutBinding
import io.element.android.x.textcomposer.databinding.ViewRichTextMenuButtonBinding
import io.element.android.x.textcomposer.tools.setTextIfDifferent
import uniffi.wysiwyg_composer.ActionState
import uniffi.wysiwyg_composer.ComposerAction
-import io.element.android.x.element.resources.R as ElementR
// Imported from Element Android
class RichTextComposerLayout @JvmOverloads constructor(
@@ -247,28 +247,28 @@ class RichTextComposerLayout @JvmOverloads constructor(
private fun setupRichTextMenu() {
addRichTextMenuItem(
- ElementR.drawable.ic_composer_bold,
+ R.drawable.ic_composer_bold,
ElementR.string.rich_text_editor_format_bold,
ComposerAction.BOLD
) {
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Bold)
}
addRichTextMenuItem(
- ElementR.drawable.ic_composer_italic,
+ R.drawable.ic_composer_italic,
ElementR.string.rich_text_editor_format_italic,
ComposerAction.ITALIC
) {
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Italic)
}
addRichTextMenuItem(
- ElementR.drawable.ic_composer_underlined,
+ R.drawable.ic_composer_underlined,
ElementR.string.rich_text_editor_format_underline,
ComposerAction.UNDERLINE
) {
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Underline)
}
addRichTextMenuItem(
- ElementR.drawable.ic_composer_strikethrough,
+ R.drawable.ic_composer_strikethrough,
ElementR.string.rich_text_editor_format_strikethrough,
ComposerAction.STRIKE_THROUGH
) {
@@ -485,7 +485,7 @@ class RichTextComposerLayout @JvmOverloads constructor(
} else {
views.composerModeGroup.isGone = true
(mode as? MessageComposerMode.Normal)?.content?.let { text ->
- // TODO: un-comment once we update to a version of the lib > 0.8.0
+ // TODO un-comment once we update to a version of the lib > 0.8.0
/*
if (isTextFormattingEnabled) {
replaceFormattedContent(text)
diff --git a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt
index 870fe1e657..6efa2e633b 100644
--- a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt
+++ b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/TextComposer.kt
@@ -22,81 +22,81 @@ import io.element.android.x.element.resources.R as ElementR
@Composable
fun TextComposer(
- onSendMessage: (String) -> Unit,
- modifier: Modifier = Modifier,
fullscreen: Boolean,
- onFullscreenToggle: () -> Unit,
+ composerText: String?,
composerMode: MessageComposerMode,
- onCloseSpecialMode: () -> Unit,
- onComposerTextChange: (CharSequence) -> Unit,
composerCanSendMessage: Boolean,
- composerText: String?,
+ modifier: Modifier = Modifier,
+ onSendMessage: (String) -> Unit = {},
+ onFullscreenToggle: () -> Unit = {},
+ onCloseSpecialMode: () -> Unit = {},
+ onComposerTextChange: (CharSequence) -> Unit = {},
) {
if (LocalInspectionMode.current) {
FakeComposer(modifier)
- return
- }
+ } else {
+ val isInDarkMode = isSystemInDarkTheme()
+ AndroidView(
+ modifier = modifier,
+ factory = { context ->
+ RichTextComposerLayout(context).apply {
+ // Sets up listeners for View -> Compose communication
+ this.callback = object : Callback {
+ override fun onRichContentSelected(contentUri: Uri): Boolean {
+ return false
+ }
- val isInDarkMode = isSystemInDarkTheme()
- AndroidView(
- modifier = modifier,
- factory = { context ->
- RichTextComposerLayout(context).apply {
- // Sets up listeners for View -> Compose communication
- this.callback = object : Callback {
- override fun onRichContentSelected(contentUri: Uri): Boolean {
- return false
- }
+ override fun onTextChanged(text: CharSequence) {
+ onComposerTextChange(text)
+ }
- override fun onTextChanged(text: CharSequence) {
- onComposerTextChange(text)
- }
+ override fun onCloseRelatedMessage() {
+ onCloseSpecialMode()
+ }
- override fun onCloseRelatedMessage() {
- onCloseSpecialMode()
- }
+ override fun onSendMessage(text: CharSequence) {
+ // text contains markdown.
+ onSendMessage(text.toString())
+ }
- override fun onSendMessage(text: CharSequence) {
- // text contains markdown.
- onSendMessage(text.toString())
- }
+ override fun onAddAttachment() {
+ }
- override fun onAddAttachment() {
- }
+ override fun onExpandOrCompactChange() {
+ }
- override fun onExpandOrCompactChange() {
+ override fun onFullScreenModeChanged() {
+ onFullscreenToggle()
+ }
}
-
- override fun onFullScreenModeChanged() {
- onFullscreenToggle()
+ setFullScreen(fullscreen, animated = false, manageKeyboard = true)
+ (this as MessageComposerView).apply {
+ setup(isInDarkMode, composerMode)
}
-
- }
- setFullScreen(fullscreen, animated = false, manageKeyboard = true)
- (this as MessageComposerView).apply {
- setup(isInDarkMode, composerMode)
}
- }
- },
- update = { view ->
- // View's been inflated or state read in this block has been updated
- // Add logic here if necessary
+ },
+ update = { view ->
+ // View's been inflated or state read in this block has been updated
+ // Add logic here if necessary
- // As selectedItem is read here, AndroidView will recompose
- // whenever the state changes
- // Example of Compose -> View communication
- val messageComposerView = (view as MessageComposerView)
- view.setFullScreen(fullscreen, animated = false, manageKeyboard = false)
- messageComposerView.renderComposerMode(composerMode)
- messageComposerView.sendButton.isInvisible = !composerCanSendMessage
- messageComposerView.setTextIfDifferent(composerText ?: "")
- messageComposerView.editText.requestFocus()
- }
- )
+ // As selectedItem is read here, AndroidView will recompose
+ // whenever the state changes
+ // Example of Compose -> View communication
+ val messageComposerView = (view as MessageComposerView)
+ view.setFullScreen(fullscreen, animated = false, manageKeyboard = false)
+ messageComposerView.renderComposerMode(composerMode)
+ messageComposerView.sendButton.isInvisible = !composerCanSendMessage
+ messageComposerView.setTextIfDifferent(composerText ?: "")
+ messageComposerView.editText.requestFocus()
+ }
+ )
+ }
}
@Composable
-private fun FakeComposer(modifier: Modifier) {
+private fun FakeComposer(
+ modifier: Modifier = Modifier,
+) {
// AndroidView is not Available in this mode, just render a Text
Box(
modifier = modifier
diff --git a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/tools/ViewExtensions.kt b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/tools/ViewExtensions.kt
index 649221c2bd..fa0a218d19 100644
--- a/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/tools/ViewExtensions.kt
+++ b/libraries/textcomposer/src/main/java/io/element/android/x/textcomposer/tools/ViewExtensions.kt
@@ -1,7 +1,11 @@
package io.element.android.x.textcomposer.tools
import android.view.ViewGroup
-import androidx.transition.*
+import androidx.transition.ChangeBounds
+import androidx.transition.Fade
+import androidx.transition.Transition
+import androidx.transition.TransitionManager
+import androidx.transition.TransitionSet
fun ViewGroup.animateLayoutChange(animationDuration: Long, transitionComplete: (() -> Unit)? = null) {
val transition = TransitionSet().apply {
diff --git a/libraries/elementresources/src/main/res/color/selector_rich_text_menu_icon.xml b/libraries/textcomposer/src/main/res/color/selector_rich_text_menu_icon.xml
similarity index 100%
rename from libraries/elementresources/src/main/res/color/selector_rich_text_menu_icon.xml
rename to libraries/textcomposer/src/main/res/color/selector_rich_text_menu_icon.xml
diff --git a/libraries/textcomposer/src/main/res/drawable/bg_composer_rich_bottom_sheet.xml b/libraries/textcomposer/src/main/res/drawable/bg_composer_rich_bottom_sheet.xml
deleted file mode 100644
index 47364373f7..0000000000
--- a/libraries/textcomposer/src/main/res/drawable/bg_composer_rich_bottom_sheet.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/libraries/elementresources/src/main/res/drawable/bg_rich_text_menu_button.xml b/libraries/textcomposer/src/main/res/drawable/bg_rich_text_menu_button.xml
similarity index 100%
rename from libraries/elementresources/src/main/res/drawable/bg_rich_text_menu_button.xml
rename to libraries/textcomposer/src/main/res/drawable/bg_rich_text_menu_button.xml
diff --git a/libraries/textcomposer/src/main/res/drawable/bottomsheet_handle.xml b/libraries/textcomposer/src/main/res/drawable/bottomsheet_handle.xml
index 89ccf57ed0..f1bb917c61 100644
--- a/libraries/textcomposer/src/main/res/drawable/bottomsheet_handle.xml
+++ b/libraries/textcomposer/src/main/res/drawable/bottomsheet_handle.xml
@@ -1,6 +1,7 @@
-
-
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_bold.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_bold.xml
new file mode 100644
index 0000000000..17adfc3d35
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_bold.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_collapse.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_collapse.xml
index 724a833761..3e24b2d62e 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_composer_collapse.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_collapse.xml
@@ -5,5 +5,5 @@
android:viewportHeight="20">
+ android:pathData="M10.708,10Q10.438,10 10.219,9.781Q10,9.562 10,9.292V4.542Q10,4.354 10.146,4.219Q10.292,4.083 10.458,4.083Q10.646,4.083 10.781,4.219Q10.917,4.354 10.917,4.542V8.438L16.375,3Q16.5,2.854 16.688,2.854Q16.875,2.854 17,3Q17.146,3.125 17.146,3.312Q17.146,3.5 17,3.625L11.562,9.083H15.458Q15.646,9.083 15.781,9.229Q15.917,9.375 15.917,9.542Q15.917,9.729 15.781,9.865Q15.646,10 15.458,10ZM3,17Q2.854,16.875 2.854,16.688Q2.854,16.5 3,16.375L8.438,10.917H4.542Q4.354,10.917 4.219,10.771Q4.083,10.625 4.083,10.458Q4.083,10.271 4.219,10.135Q4.354,10 4.542,10H9.292Q9.562,10 9.781,10.219Q10,10.438 10,10.708V15.458Q10,15.646 9.854,15.781Q9.708,15.917 9.542,15.917Q9.354,15.917 9.219,15.781Q9.083,15.646 9.083,15.458V11.562L3.625,17Q3.5,17.146 3.312,17.146Q3.125,17.146 3,17Z" />
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_full_screen.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_full_screen.xml
index de1862c09b..4c88f9063c 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_composer_full_screen.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_full_screen.xml
@@ -1,9 +1,9 @@
+ android:width="48dp"
+ android:height="48dp"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ android:pathData="M17.125,31.5C16.944,31.5 16.795,31.441 16.677,31.323C16.559,31.205 16.5,31.056 16.5,30.875V25.875C16.5,25.694 16.559,25.545 16.677,25.427C16.795,25.309 16.944,25.25 17.125,25.25C17.306,25.25 17.455,25.309 17.573,25.427C17.691,25.545 17.75,25.694 17.75,25.875V29.375L29.375,17.75H25.875C25.694,17.75 25.545,17.691 25.427,17.573C25.309,17.455 25.25,17.306 25.25,17.125C25.25,16.944 25.309,16.795 25.427,16.677C25.545,16.559 25.694,16.5 25.875,16.5H30.875C31.056,16.5 31.205,16.559 31.323,16.677C31.441,16.795 31.5,16.944 31.5,17.125V22.125C31.5,22.306 31.441,22.455 31.323,22.573C31.205,22.691 31.056,22.75 30.875,22.75C30.694,22.75 30.545,22.691 30.427,22.573C30.309,22.455 30.25,22.306 30.25,22.125V18.625L18.625,30.25H22.125C22.306,30.25 22.455,30.309 22.573,30.427C22.691,30.545 22.75,30.694 22.75,30.875C22.75,31.056 22.691,31.205 22.573,31.323C22.455,31.441 22.306,31.5 22.125,31.5H17.125Z"
+ android:fillColor="#C1C6CD" />
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_italic.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_italic.xml
new file mode 100644
index 0000000000..97050d52f9
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_italic.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_close.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
index c461470de5..44343de281 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
@@ -3,7 +3,7 @@
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
-
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
index 4556974221..a5ef981c5b 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
@@ -3,10 +3,10 @@
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
-
-
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_save.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_save.xml
index f270d6f8ae..e447fdc6af 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_save.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_rich_text_save.xml
@@ -3,14 +3,14 @@
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
-
-
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_strikethrough.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_strikethrough.xml
new file mode 100644
index 0000000000..505558409a
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_strikethrough.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_composer_underlined.xml b/libraries/textcomposer/src/main/res/drawable/ic_composer_underlined.xml
new file mode 100644
index 0000000000..296e16f3d8
--- /dev/null
+++ b/libraries/textcomposer/src/main/res/drawable/ic_composer_underlined.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_quote.xml b/libraries/textcomposer/src/main/res/drawable/ic_quote.xml
index 0689651f1d..e287c9296d 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_quote.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_quote.xml
@@ -3,12 +3,12 @@
android:height="14dp"
android:viewportWidth="20"
android:viewportHeight="14">
-
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_reply.xml b/libraries/textcomposer/src/main/res/drawable/ic_reply.xml
index f23730624f..80eeab00c9 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_reply.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_reply.xml
@@ -1,11 +1,20 @@
-
-
+
-
+
+ android:strokeColor="#000000"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_add.xml b/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_add.xml
index 3a90a40902..9dc6ed03e9 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_add.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_add.xml
@@ -3,13 +3,13 @@
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
-
-
+
+
diff --git a/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_send.xml b/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_send.xml
index 0f99c1670e..18afb70d6d 100644
--- a/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_send.xml
+++ b/libraries/textcomposer/src/main/res/drawable/ic_rich_composer_send.xml
@@ -3,10 +3,10 @@
android:height="36dp"
android:viewportWidth="36"
android:viewportHeight="36">
-
-
+
+
diff --git a/libraries/textcomposer/src/main/res/layout/composer_rich_text_layout.xml b/libraries/textcomposer/src/main/res/layout/composer_rich_text_layout.xml
index d099c72cab..0e82ca381b 100644
--- a/libraries/textcomposer/src/main/res/layout/composer_rich_text_layout.xml
+++ b/libraries/textcomposer/src/main/res/layout/composer_rich_text_layout.xml
@@ -81,7 +81,8 @@
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
app:tint="?vctr_content_tertiary" />
-
-
- .androidConfig() {
+fun CommonExtension<*, *, *, *>.androidConfig(project: Project) {
defaultConfig {
compileSdk = Versions.compileSdk
minSdk = Versions.minSdk
@@ -18,6 +19,12 @@ fun CommonExtension<*, *, *, *>.androidConfig() {
testOptions {
unitTests.isReturnDefaultValues = true
}
+
+ lint {
+ lintConfig = File("${project.rootDir}/tools/lint/lint.xml")
+ checkDependencies = true
+ abortOnError = true
+ }
}
fun CommonExtension<*, *, *, *>.composeConfig() {
@@ -35,5 +42,11 @@ fun CommonExtension<*, *, *, *>.composeConfig() {
add("META-INF/LGPL2.1")
}
}
+
+ lint {
+ // Extra rules for compose
+ error.add("ComposableLambdaParameterNaming")
+ error.add("ComposableLambdaParameterPosition")
+ }
}
diff --git a/plugins/src/main/java/extension/DependencyHandleScope.kt b/plugins/src/main/java/extension/DependencyHandleScope.kt
index 09fdd1bb23..d45fec0c94 100644
--- a/plugins/src/main/java/extension/DependencyHandleScope.kt
+++ b/plugins/src/main/java/extension/DependencyHandleScope.kt
@@ -5,8 +5,17 @@ import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.debugImplem
import gradle.kotlin.dsl.accessors._4b7ad2363fc1fce7c774e054dc9a9300.implementation
import org.gradle.kotlin.dsl.DependencyHandlerScope
+/**
+ * Dependencies used by all the modules
+ */
+fun DependencyHandlerScope.commonDependencies() {
+ implementation("com.jakewharton.timber:timber:5.0.1")
+}
-fun DependencyHandlerScope.composeDependencies(){
+/**
+ * Dependencies used by all the modules with composable items
+ */
+fun DependencyHandlerScope.composeDependencies() {
val composeBom = platform("androidx.compose:compose-bom:2022.11.00")
implementation(composeBom)
androidTestImplementation(composeBom)
@@ -22,5 +31,6 @@ fun DependencyHandlerScope.composeDependencies(){
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
implementation("com.airbnb.android:showkase:1.0.0-beta14")
+ implementation("org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.5")
}
diff --git a/plugins/src/main/java/io.element.android-compose-application.gradle.kts b/plugins/src/main/java/io.element.android-compose-application.gradle.kts
index 8814bb7682..807ac5245d 100644
--- a/plugins/src/main/java/io.element.android-compose-application.gradle.kts
+++ b/plugins/src/main/java/io.element.android-compose-application.gradle.kts
@@ -1,4 +1,8 @@
+/**
+ * This will generate the plugin "io.element.android-compose-application", used only in the module `app`.
+ */
import extension.androidConfig
+import extension.commonDependencies
import extension.composeConfig
import extension.composeDependencies
@@ -8,10 +12,11 @@ plugins {
}
android {
- androidConfig()
+ androidConfig(project)
composeConfig()
}
dependencies {
+ commonDependencies()
composeDependencies()
}
diff --git a/plugins/src/main/java/io.element.android-compose-library.gradle.kts b/plugins/src/main/java/io.element.android-compose-library.gradle.kts
index 736b47140a..fdb73e897e 100644
--- a/plugins/src/main/java/io.element.android-compose-library.gradle.kts
+++ b/plugins/src/main/java/io.element.android-compose-library.gradle.kts
@@ -1,4 +1,8 @@
+/**
+ * This will generate the plugin "io.element.android-compose-library", used in android library with compose modules.
+ */
import extension.androidConfig
+import extension.commonDependencies
import extension.composeConfig
import extension.composeDependencies
@@ -7,12 +11,12 @@ plugins {
id("kotlin-android")
}
-
android {
- androidConfig()
+ androidConfig(project)
composeConfig()
}
dependencies {
+ commonDependencies()
composeDependencies()
}
diff --git a/plugins/src/main/java/io.element.android-library.gradle.kts b/plugins/src/main/java/io.element.android-library.gradle.kts
index 4283de3fa2..ed74db1f96 100644
--- a/plugins/src/main/java/io.element.android-library.gradle.kts
+++ b/plugins/src/main/java/io.element.android-library.gradle.kts
@@ -1,4 +1,8 @@
+/**
+ * This will generate the plugin "io.element.android-library", used in android library without compose modules.
+ */
import extension.androidConfig
+import extension.commonDependencies
plugins {
id("com.android.library")
@@ -6,5 +10,9 @@ plugins {
}
android {
- androidConfig()
+ androidConfig(project)
+}
+
+dependencies {
+ commonDependencies()
}
diff --git a/tools/danger/dangerfile-lint.js b/tools/danger/dangerfile-lint.js
new file mode 100644
index 0000000000..b0531fef9b
--- /dev/null
+++ b/tools/danger/dangerfile-lint.js
@@ -0,0 +1,29 @@
+import { schedule } from 'danger'
+
+/**
+ * Ref and documentation: https://github.com/damian-burke/danger-plugin-lint-report
+ * This file will check all the error in XML Checkstyle format.
+ * It covers, lint, ktlint, and detekt errors
+ */
+
+const reporter = require("danger-plugin-lint-report")
+schedule(reporter.scan({
+ /**
+ * File mask used to find XML checkstyle reports.
+ */
+ fileMask: "**/reports/**/**.xml",
+ /**
+ * If set to true, the severity will be used to switch between the different message formats (message, warn, fail).
+ */
+ reportSeverity: true,
+ /**
+ * If set to true, only issues will be reported that are contained in the current changeset (line comparison).
+ * If set to false, all issues that are in modified files will be reported.
+ */
+ requireLineModification: false,
+ /**
+ * Optional: Sets a prefix foreach violation message.
+ * This can be useful if there are multiple reports being parsed to make them distinguishable.
+ */
+ // outputPrefix?: ""
+}))
diff --git a/tools/danger/dangerfile.js b/tools/danger/dangerfile.js
new file mode 100644
index 0000000000..a9be0171d7
--- /dev/null
+++ b/tools/danger/dangerfile.js
@@ -0,0 +1,128 @@
+const {danger, warn} = require('danger')
+
+/**
+ * Note: if you update the checks in this file, please also update the file ./docs/danger.md
+ */
+
+// Useful to see what we got in danger object
+// warn(JSON.stringify(danger))
+
+const pr = danger.github.pr
+const github = danger.github
+// User who has created the PR.
+const user = pr.user.login
+const modified = danger.git.modified_files
+const created = danger.git.created_files
+const editedFiles = [...modified, ...created]
+
+// Check that the PR has a description
+if (pr.body.length == 0) {
+ warn("Please provide a description for this PR.")
+}
+
+// Warn when there is a big PR
+if (editedFiles.length > 50) {
+ message("This pull request seems relatively large. Please consider splitting it into multiple smaller ones.")
+}
+
+// Request a changelog for each PR
+const changelogAllowList = [
+ "dependabot[bot]",
+]
+
+const requiresChangelog = !changelogAllowList.includes(user)
+
+if (requiresChangelog) {
+ const changelogFiles = editedFiles.filter(file => file.startsWith("changelog.d/"))
+
+ if (changelogFiles.length == 0) {
+ warn("Please add a changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ } else {
+ const validTowncrierExtensions = [
+ "bugfix",
+ "doc",
+ "feature",
+ "misc",
+ "sdk",
+ "wip",
+ ]
+ if (!changelogFiles.every(file => validTowncrierExtensions.includes(file.split(".").pop()))) {
+ fail("Invalid extension for changelog. See instructions [here](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#changelog)")
+ }
+ }
+}
+
+// check that frozen classes have not been modified
+const frozenClasses = [
+]
+
+frozenClasses.forEach(frozen => {
+ if (editedFiles.some(file => file.endsWith(frozen))) {
+ fail("Frozen class `" + frozen + "` has been modified. Please do not modify frozen class.")
+ }
+ }
+)
+
+// Check for a sign-off
+const signOff = "Signed-off-by:"
+
+// Please add new names following the alphabetical order.
+const allowList = [
+ "amitkma",
+ "aringenbach",
+ "BillCarsonFr",
+ "bmarty",
+ "Claire1817",
+ "dependabot[bot]",
+ "ericdecanini",
+ "fedrunov",
+ "Florian14",
+ "ganfra",
+ "jmartinesp",
+ "jonnyandrew",
+ "kittykat",
+ "langleyd",
+ "MadLittleMods",
+ "manuroe",
+ "mnaturel",
+ "onurays",
+ "ouchadam",
+ "stefanceriu",
+ "yostyle",
+]
+
+const requiresSignOff = !allowList.includes(user)
+
+if (requiresSignOff) {
+ const hasPRBodySignOff = pr.body.includes(signOff)
+ const hasCommitSignOff = danger.git.commits.every(commit => commit.message.includes(signOff))
+ if (!hasPRBodySignOff && !hasCommitSignOff) {
+ fail("Please add a sign-off to either the PR description or to the commits themselves. See instructions [here](https://matrix-org.github.io/synapse/latest/development/contributing_guide.html#sign-off).")
+ }
+}
+
+// Check for screenshots on view changes
+const hasChangedViews = editedFiles.filter(file => file.includes("/layout")).length > 0
+if (hasChangedViews) {
+ if (!pr.body.includes("user-images")) {
+ warn("You seem to have made changes to views. Please consider adding screenshots.")
+ }
+}
+
+// Check for pngs on resources
+const hasPngs = editedFiles.filter(file => file.toLowerCase().endsWith(".png")).length > 0
+if (hasPngs) {
+ warn("You seem to have made changes to some images. Please consider using an vector drawable.")
+}
+
+// Check for reviewers
+if (github.requested_reviewers.users.length == 0 && !pr.draft) {
+ warn("Please add a reviewer to your PR.")
+}
+
+// Check that translations have not been modified by developers
+if (user != "RiotTranslateBot") {
+ if (editedFiles.some(file => file.endsWith("strings.xml") && !file.endsWith("values/strings.xml"))) {
+ fail("Some translation files have been edited. Only user `RiotTranslateBot` (i.e. translations coming from Weblate) is allowed to do that.\nPlease read more about translations management [in the doc](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md#internationalisation).")
+ }
+}
diff --git a/tools/detekt/detekt.yml b/tools/detekt/detekt.yml
new file mode 100644
index 0000000000..6659692329
--- /dev/null
+++ b/tools/detekt/detekt.yml
@@ -0,0 +1,150 @@
+# Default rules: https://github.com/detekt/detekt/blob/main/detekt-core/src/main/resources/default-detekt-config.yml
+
+style:
+ MaxLineLength:
+ # Default is 120
+ maxLineLength: 160
+ MagicNumber:
+ active: false
+ ReturnCount:
+ active: false
+ UnnecessaryAbstractClass:
+ active: false
+ FunctionOnlyReturningConstant:
+ active: false
+ UnusedPrivateMember:
+ # TODO Enable it
+ active: false
+ ThrowsCount:
+ active: false
+ LoopWithTooManyJumpStatements:
+ active: false
+ SerialVersionUIDInSerializableClass:
+ active: false
+ ProtectedMemberInFinalClass:
+ active: false
+ UseCheckOrError:
+ active: false
+
+empty-blocks:
+ EmptyFunctionBlock:
+ active: false
+ EmptySecondaryConstructor:
+ active: false
+
+potential-bugs:
+ ImplicitDefaultLocale:
+ active: false
+
+exceptions:
+ TooGenericExceptionCaught:
+ active: false
+ SwallowedException:
+ active: false
+ ThrowingExceptionsWithoutMessageOrCause:
+ active: false
+ TooGenericExceptionThrown:
+ active: false
+ InstanceOfCheckForException:
+ active: false
+
+complexity:
+ TooManyFunctions:
+ active: false
+ LongMethod:
+ active: false
+ LongParameterList:
+ active: false
+ CyclomaticComplexMethod:
+ active: false
+ NestedBlockDepth:
+ active: false
+ ComplexCondition:
+ active: false
+ LargeClass:
+ active: false
+
+naming:
+ VariableNaming:
+ # TODO Enable it
+ active: false
+ TopLevelPropertyNaming:
+ # TODO Enable it
+ active: false
+ FunctionNaming:
+ active: true
+ ignoreAnnotated: ['Composable']
+
+performance:
+ SpreadOperator:
+ active: false
+
+# Note: all rules for `comments` are disabled by default, but I put them here to be aware of their existence
+comments:
+ AbsentOrWrongFileLicense:
+ active: false
+ licenseTemplateFile: 'license.template'
+ licenseTemplateIsRegex: false
+ CommentOverPrivateFunction:
+ active: false
+ CommentOverPrivateProperty:
+ active: false
+ DeprecatedBlockTag:
+ active: true
+ EndOfSentenceFormat:
+ active: true
+ OutdatedDocumentation:
+ active: true
+ UndocumentedPublicClass:
+ active: false
+ UndocumentedPublicFunction:
+ active: false
+ UndocumentedPublicProperty:
+ active: false
+
+TwitterCompose:
+ CompositionLocalAllowlist:
+ active: true
+ # You can optionally define a list of CompositionLocals that are allowed here
+ # allowedCompositionLocals: LocalSomething,LocalSomethingElse
+ CompositionLocalNaming:
+ active: true
+ ContentEmitterReturningValues:
+ active: true
+ # You can optionally add your own composables here
+ # contentEmitters: MyComposable,MyOtherComposable
+ ModifierComposable:
+ active: true
+ ModifierMissing:
+ active: true
+ ModifierReused:
+ active: true
+ ModifierWithoutDefault:
+ active: true
+ MultipleEmitters:
+ active: true
+ # You can optionally add your own composables here
+ # contentEmitters: MyComposable,MyOtherComposable
+ MutableParams:
+ active: true
+ ComposableNaming:
+ active: true
+ # You can optionally disable the checks in this rule for regex matches against the composable name (e.g. molecule presenters)
+ # allowedComposableFunctionNames: .*Presenter,.*MoleculePresenter
+ ComposableParamOrder:
+ active: true
+ PreviewNaming:
+ active: true
+ PreviewPublic:
+ active: true
+ # You can optionally disable that only previews with @PreviewParameter are flagged
+ previewPublicOnlyIfParams: false
+ RememberMissing:
+ active: true
+ UnstableCollections:
+ active: true
+ ViewModelForwarding:
+ ## TODO Set to true later
+ active: false
+ ViewModelInjection:
+ active: true
diff --git a/tools/lint/lint.xml b/tools/lint/lint.xml
new file mode 100644
index 0000000000..816fcb633a
--- /dev/null
+++ b/tools/lint/lint.xml
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+