Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3cc84bcf3 | |||
| 4e89e623c6 | |||
| 3d07b0b025 |
555
.editorconfig
555
.editorconfig
@ -1,555 +0,0 @@
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
insert_final_newline = false
|
||||
max_line_length = 120
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
ij_smart_tabs = false
|
||||
ij_visual_guides = none
|
||||
ij_wrap_on_typing = false
|
||||
|
||||
[*.java]
|
||||
ij_java_align_consecutive_assignments = false
|
||||
ij_java_align_consecutive_variable_declarations = false
|
||||
ij_java_align_group_field_declarations = false
|
||||
ij_java_align_multiline_annotation_parameters = false
|
||||
ij_java_align_multiline_array_initializer_expression = false
|
||||
ij_java_align_multiline_assignment = false
|
||||
ij_java_align_multiline_binary_operation = false
|
||||
ij_java_align_multiline_chained_methods = false
|
||||
ij_java_align_multiline_extends_list = false
|
||||
ij_java_align_multiline_for = true
|
||||
ij_java_align_multiline_method_parentheses = false
|
||||
ij_java_align_multiline_parameters = true
|
||||
ij_java_align_multiline_parameters_in_calls = false
|
||||
ij_java_align_multiline_parenthesized_expression = false
|
||||
ij_java_align_multiline_records = true
|
||||
ij_java_align_multiline_resources = true
|
||||
ij_java_align_multiline_ternary_operation = false
|
||||
ij_java_align_multiline_text_blocks = false
|
||||
ij_java_align_multiline_throws_list = false
|
||||
ij_java_align_subsequent_simple_methods = false
|
||||
ij_java_align_throws_keyword = false
|
||||
ij_java_align_types_in_multi_catch = true
|
||||
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_add_space = false
|
||||
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_not_wrap_after_single_annotation_in_parameter = 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_add_space_on_reformat = 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_multi_catch_types_wrap = normal
|
||||
ij_java_names_count_to_use_import_on_demand = 99
|
||||
ij_java_new_line_after_lparen_in_annotation = false
|
||||
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_annotation = false
|
||||
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_annotation_eq = 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
|
||||
|
||||
[.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_add_space = false
|
||||
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
|
||||
|
||||
[{*.gant,*.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_add_space = false
|
||||
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_enable_groovydoc_formatting = true
|
||||
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_add_space_on_reformat = 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_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
|
||||
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_record_parentheses = false
|
||||
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_chain_calls_after_dot = false
|
||||
ij_groovy_wrap_long_lines = false
|
||||
|
||||
[{*.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 = false
|
||||
ij_kotlin_allow_trailing_comma_on_call_site = false
|
||||
ij_kotlin_assignment_wrap = normal
|
||||
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_add_space = false
|
||||
ij_kotlin_block_comment_at_first_column = true
|
||||
ij_kotlin_call_parameters_new_line_after_left_paren = true
|
||||
ij_kotlin_call_parameters_right_paren_on_new_line = true
|
||||
ij_kotlin_call_parameters_wrap = on_every_item
|
||||
ij_kotlin_catch_on_new_line = false
|
||||
ij_kotlin_class_annotation_wrap = split_into_lines
|
||||
ij_kotlin_code_style_defaults = KOTLIN_OFFICIAL
|
||||
ij_kotlin_continuation_indent_for_chained_calls = false
|
||||
ij_kotlin_continuation_indent_for_expression_bodies = false
|
||||
ij_kotlin_continuation_indent_in_argument_lists = false
|
||||
ij_kotlin_continuation_indent_in_elvis = false
|
||||
ij_kotlin_continuation_indent_in_if_conditions = false
|
||||
ij_kotlin_continuation_indent_in_parameter_lists = false
|
||||
ij_kotlin_continuation_indent_in_supertype_lists = false
|
||||
ij_kotlin_else_on_new_line = false
|
||||
ij_kotlin_enum_constants_wrap = off
|
||||
ij_kotlin_extends_list_wrap = normal
|
||||
ij_kotlin_field_annotation_wrap = split_into_lines
|
||||
ij_kotlin_finally_on_new_line = false
|
||||
ij_kotlin_if_rparen_on_new_line = true
|
||||
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 = 2
|
||||
ij_kotlin_keep_blank_lines_in_code = 2
|
||||
ij_kotlin_keep_blank_lines_in_declarations = 2
|
||||
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_add_space_on_reformat = false
|
||||
ij_kotlin_line_comment_at_first_column = true
|
||||
ij_kotlin_method_annotation_wrap = split_into_lines
|
||||
ij_kotlin_method_call_chain_wrap = normal
|
||||
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 = on_every_item
|
||||
ij_kotlin_name_count_to_use_star_import = 5
|
||||
ij_kotlin_name_count_to_use_star_import_for_members = 3
|
||||
ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.**
|
||||
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 = 1
|
||||
ij_kotlin_wrap_first_method_in_call_chain = false
|
||||
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,14 +1,7 @@
|
||||
.idea/
|
||||
*.iml
|
||||
.gradle/
|
||||
local.properties
|
||||
# sign.properties
|
||||
.DS_Store
|
||||
captures/
|
||||
build/
|
||||
release-app/
|
||||
test-app/
|
||||
scripts/apk-channel/
|
||||
app/src/test/java/com/gh/gamecenter
|
||||
app/src/main/assets-debug/
|
||||
app/src/main/assets-release/
|
||||
/.idea
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
160
.gitlab-ci.yml
160
.gitlab-ci.yml
@ -1,160 +0,0 @@
|
||||
# commit_sha 文件记录上一次成功流水线的commit sha,用于定时计划检测是否有新代码提交,有就执行流水线,没有就终止流水线
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull
|
||||
|
||||
# 将打包&发送apk包邮件job 和代码分析job 并行执行
|
||||
stages:
|
||||
- build&analyze
|
||||
- oss-upload&send-email
|
||||
- ci_sonar_mail
|
||||
|
||||
# 阻止了 合并请求 或 push(分支和标签)的流水线。 最后的 when: always 规则运行所有其他流水线类型,包括定时计划流水线。
|
||||
workflow:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "push"'
|
||||
when: always
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
when: never
|
||||
- when: always
|
||||
|
||||
before_script:
|
||||
# 检查是否存在 commit_sha 文件
|
||||
- if [ -f commit_sha ]; then cat commit_sha; else echo "0000000" > commit_sha; fi
|
||||
- export BEFORE_COMMIT_SHA=$(cat commit_sha)
|
||||
# 比较commit sha ,若与上一次成功流水线的commit sha 相同,则退出流水线
|
||||
- if [ "$CI_COMMIT_SHA" == "$BEFORE_COMMIT_SHA" ] && [ "$CI_PIPELINE_SOURCE" != "web" ]; then exit 137; fi
|
||||
|
||||
# 使用 .post 阶段使作业在流水线的末尾运行。.post 始终是流水线的最后阶段。
|
||||
change_commit:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: .post
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
# 更新 commit_sha
|
||||
- if [ "$CI_COMMIT_SHA" != "$BEFORE_COMMIT_SHA" ]; then echo $CI_COMMIT_SHA > commit_sha; fi
|
||||
cache:
|
||||
# 不同的分支采用不同的 cache,防止分支之间相互影响
|
||||
key: "${CI_COMMIT_REF_SLUG}_commit_sha"
|
||||
paths:
|
||||
- commit_sha
|
||||
policy: pull-push
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
|
||||
android_build:
|
||||
tags:
|
||||
# - local-runner
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: hub.shanqu.cc/library/ci-android:jdk11-sdk31-33
|
||||
resource_group: android_build
|
||||
variables:
|
||||
GIT_SUBMODULE_STRATEGY: recursive
|
||||
KUBERNETES_CPU_LIMIT: "10"
|
||||
script:
|
||||
- export GRADLE_USER_HOME=/home/gitlab-runner/ci-build-cache/$CI_PROJECT_PATH/.gradle
|
||||
- chmod +x ./gradlew
|
||||
- ./scripts/jenkins_build.sh $CI_COMMIT_REF_NAME $BEFORE_COMMIT_SHA $CI_COMMIT_SHA
|
||||
#设置打包后的产物,用于job之间共享
|
||||
artifacts:
|
||||
paths:
|
||||
- app/build/tmp/*.apk
|
||||
expire_in: 48 hrs # 指定附件上载后保存的时间24h,默认永久在Gitlab保存
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
# 代码检查
|
||||
sonarqube_analysis:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: build&analyze
|
||||
image: hub.shanqu.cc/library/sonar-scanner-cli:latest
|
||||
dependencies: [] #禁止传递来的artifact
|
||||
script:
|
||||
## 获取项目的一级组和二级组和项目名作为projectKey,例如projectKey=platform-backend-eci-monitor
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- sonar-scanner
|
||||
-Dsonar.host.url=http://sonarqube-server.sonarqube:9000/
|
||||
-Dsonar.login=be43de7264ce4c4766eb0c020373c3e74e6df257
|
||||
-Dsonar.jacoco.reportPaths=target/jacoco.exec
|
||||
-Dsonar.projectKey=$group
|
||||
-Dsonar.projectName=$CI_PROJECT_PATH
|
||||
-Dsonar.sourceEncoding=UTF-8
|
||||
-Dsonar.exclusions=**/vendor/**,**/errcode/**
|
||||
-Dsonar.gitlab.project_id=$CI_PROJECT_ID
|
||||
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
|
||||
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.java.binaries=.
|
||||
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
## 发送简易检测结果报告
|
||||
send_sonar_report:
|
||||
tags:
|
||||
- offline-test
|
||||
stage: ci_sonar_mail
|
||||
image: hub.shanqu.cc/library/docker:latest
|
||||
# 此job 跳过拉取git代码
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
script:
|
||||
- group=`echo $CI_PROJECT_PATH | sed 's#/#-#g'`
|
||||
- docker run -e PROJECTKEY=$group -e EMAIL=$GITLAB_USER_EMAIL -e BRANCH=$CI_COMMIT_REF_NAME --name send-email --rm hub.shanqu.cc/platform/send-sonar-report:latest
|
||||
allow_failure:
|
||||
exit_codes: 137
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
oss-upload&send-email:
|
||||
tags:
|
||||
- sysadm-devops
|
||||
stage: oss-upload&send-email
|
||||
image: hub.shanqu.cc/devops/android-apk-oss-upload:latest
|
||||
id_tokens:
|
||||
VAULT_ID_TOKEN:
|
||||
aud: https://vault.shanqu.cc
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
VAULT_ADDR: https://vault.shanqu.cc # 固定值
|
||||
VAULT_SECRET_PATH: prod/devops/android-apk-oss-upload # 固定值
|
||||
VAULT_ROLE: android-apk-oss-upload # 固定值
|
||||
ENDPOINT: "tos-cn-guangzhou.ivolces.com" # 固定值
|
||||
BUCKET: "sysadm-public" # 固定值
|
||||
FILE_PATH: "app/build/tmp/" # APK 存放路径
|
||||
Email_To_List: $EMAIL_TO_LIST # 邮件接受人列表
|
||||
Email_Title: "光环助手 $CI_COMMIT_BRANCH" # 邮件标题
|
||||
PIPELINE_ID: $CI_PIPELINE_ID # 流水线id
|
||||
COMMIT_BRANCH: $CI_COMMIT_BRANCH # 提交分支
|
||||
MAIL_MESSAGE: "[$CI_COMMIT_AUTHOR] $CI_COMMIT_MESSAGE"
|
||||
needs:
|
||||
- job: android_build
|
||||
artifacts: true
|
||||
script:
|
||||
### 绑定上传参数 ###
|
||||
|
||||
- export OSS_PATH="release/dev/${CI_PROJECT_NAME}/$(date "+%Y/%m/%d")"
|
||||
### 开启上传 ###
|
||||
- /usr/local/bin/python /upload.py
|
||||
### 发送邮件
|
||||
- /usr/local/bin/python /ci-android-mail-jira-comment.py
|
||||
only:
|
||||
- dev
|
||||
- release
|
||||
|
||||
13
.gitmodules
vendored
13
.gitmodules
vendored
@ -1,13 +0,0 @@
|
||||
[submodule "libraries/LGLibrary"]
|
||||
path = libraries/LGLibrary
|
||||
url = ../../../android/common-library.git
|
||||
branch = master
|
||||
[submodule "vspace-bridge"]
|
||||
path = vspace-bridge
|
||||
url = ../../../cwzs/android/vspace-bridge.git
|
||||
[submodule "ndownload"]
|
||||
path = ndownload
|
||||
url = ../../../android/ndownload.git
|
||||
[submodule "vasdk"]
|
||||
path = vasdk
|
||||
url = ../../../sdg/android/vasdk.git
|
||||
1
.idea/.name
generated
Normal file
1
.idea/.name
generated
Normal file
@ -0,0 +1 @@
|
||||
GH-ASSISTv1.45
|
||||
22
.idea/compiler.xml
generated
Normal file
22
.idea/compiler.xml
generated
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<resourceExtensions />
|
||||
<wildcardResourcePatterns>
|
||||
<entry name="!?*.java" />
|
||||
<entry name="!?*.form" />
|
||||
<entry name="!?*.class" />
|
||||
<entry name="!?*.groovy" />
|
||||
<entry name="!?*.scala" />
|
||||
<entry name="!?*.flex" />
|
||||
<entry name="!?*.kt" />
|
||||
<entry name="!?*.clj" />
|
||||
<entry name="!?*.aj" />
|
||||
</wildcardResourcePatterns>
|
||||
<annotationProcessing>
|
||||
<profile default="true" name="Default" enabled="false">
|
||||
<processorPath useClasspath="true" />
|
||||
</profile>
|
||||
</annotationProcessing>
|
||||
</component>
|
||||
</project>
|
||||
3
.idea/copyright/profiles_settings.xml
generated
Normal file
3
.idea/copyright/profiles_settings.xml
generated
Normal file
@ -0,0 +1,3 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
||||
6
.idea/encodings.xml
generated
Normal file
6
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
28
.idea/gradle.xml
generated
Normal file
28
.idea/gradle.xml
generated
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.10" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/buildSrc" />
|
||||
<option value="$PROJECT_DIR$/hackdex" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="myModules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
<option value="$PROJECT_DIR$/buildSrc" />
|
||||
<option value="$PROJECT_DIR$/hackdex" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
46
.idea/misc.xml
generated
Normal file
46
.idea/misc.xml
generated
Normal file
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points version="2.0" />
|
||||
</component>
|
||||
<component name="NullableNotNullManager">
|
||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
||||
<option name="myNullables">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
<option name="myNotNulls">
|
||||
<value>
|
||||
<list size="4">
|
||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
|
||||
<OptionsSetting value="true" id="Add" />
|
||||
<OptionsSetting value="true" id="Remove" />
|
||||
<OptionsSetting value="true" id="Checkout" />
|
||||
<OptionsSetting value="true" id="Update" />
|
||||
<OptionsSetting value="true" id="Status" />
|
||||
<OptionsSetting value="true" id="Edit" />
|
||||
<ConfirmationsSetting value="0" id="Add" />
|
||||
<ConfirmationsSetting value="0" id="Remove" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
11
.idea/modules.xml
generated
Normal file
11
.idea/modules.xml
generated
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/GH-ASSISTv1.45.iml" filepath="$PROJECT_DIR$/GH-ASSISTv1.45.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/buildSrc/buildSrc.iml" filepath="$PROJECT_DIR$/buildSrc/buildSrc.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/hackdex/hackdex.iml" filepath="$PROJECT_DIR$/hackdex/hackdex.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/runConfigurations.xml
generated
Normal file
12
.idea/runConfigurations.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
|
||||
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
89
CHANGELOG.md
89
CHANGELOG.md
@ -1,89 +0,0 @@
|
||||
# 版本升级备忘
|
||||
|
||||
### Ver 2.5
|
||||
* 此处写本次更新所做的业务和代码修改
|
||||
|
||||
### Ver 2.6
|
||||
* xx
|
||||
|
||||
### Ver 3.0
|
||||
* 升级账号系统(登录流程/用户信息相关/用户账号相关操作(评论,礼包...))
|
||||
* 新增收藏功能(文章/工具箱)
|
||||
* 删除用户相关的所有本地数据库
|
||||
* 重做总开服表
|
||||
* 重做首页插件化模块
|
||||
* 礼包重复领取机制改变(可重复领取的礼包,领取后立刻显示再领一个/再淘一个)
|
||||
* 游戏下载平台面板修改(加快弹出速度,不再读取本地平台图片)
|
||||
* 接入bugly(tinker)
|
||||
|
||||
### VER 3.1
|
||||
### VER 3.2
|
||||
### VER 3.3
|
||||
### VER 3.4
|
||||
### VER 3.5
|
||||
|
||||
### Ver 3.6
|
||||
* 首页游戏增加预览骨架,游戏ITEM样式微调和开服标签
|
||||
* 首页问答增加关注页面
|
||||
* 重构游戏更新管理(游戏更新/插件化/已安装的游戏),具体细节参考PackageRepository & PackageViewModel
|
||||
* 重构APP更新管理(已VersionVode为更新基准,小版本更新改为光环后台控制)
|
||||
- 删除TINKER_VERISON_NAME
|
||||
- tinker打包方式变更(以小版本作为Base包,防止与数据后台小版本更新发生冲突)
|
||||
* 社区增加版主功能(版主可以对存在的相关内容进行修改/隐藏操作,内容包括问题/回答/回答评论)
|
||||
* 社区互动引导优化(问答推荐增加`推荐关注`,回答详情增加一些交互动效)
|
||||
|
||||
### Ver 3.6.1
|
||||
* 可以后台控制关闭资讯功能
|
||||
* 版块、分类、专题详情、游戏详情、礼包详情增加预览骨架
|
||||
* 下载按钮状态可以通过接口屏蔽相应的包
|
||||
|
||||
### Ver 3.6.2
|
||||
* 资讯/问答入口和插件功能线上控制(不可逆)
|
||||
* 首页不显示已安装的游戏
|
||||
* 插件求版本功能增加内部跳转
|
||||
* 下载面板增加公告和版本说明功能
|
||||
* 接入腾讯`广点通`(广告)
|
||||
|
||||
### ver 3.6.3
|
||||
* 社区搜索修改
|
||||
- 增加 `文章/用户` 模块
|
||||
- 增加 `搜索置顶` 功能
|
||||
* 回答详情/社区文章详情修改
|
||||
- 支持文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
|
||||
- 支持关闭评论功能
|
||||
- 回答详情新增上下切换回答
|
||||
* 社区编辑框(回答/文章)修改
|
||||
- 支持批量插入图片(使用知乎Matisse实现)
|
||||
- 新增插入特殊样式,文案样式(加粗/斜体/删除线)和段落样式(引用/标题)
|
||||
* 编辑框部分 JS/CSS 使用远程文件
|
||||
|
||||
### ver 3.6.4
|
||||
* 增加浏览记录(回答/文章/资讯/游戏)
|
||||
* 回答/社区文章 增加反对功能
|
||||
* 社区编辑框增加插入文章/回答/游戏
|
||||
- 低版本兼容方案: 插入的样式默认隐藏,只有在3.6.4及以上才会显示
|
||||
* 游戏详情评分模块增加`小编评论`区域以及样式修改
|
||||
* 游戏评分增加回复功能
|
||||
|
||||
### var 3.6.5
|
||||
* 以补丁方式向外推出,并没有增加需求,只是单纯的修BUG
|
||||
|
||||
### var 3.6.6
|
||||
* 游戏详情:
|
||||
- 支持修改评分
|
||||
- 评分列表增加排序/过滤功能
|
||||
- 增加弹出系统
|
||||
* 社区相关:
|
||||
- 选择社区页面重做
|
||||
- 首页社区推荐增加推荐入口
|
||||
- 首页社区问题模块改版,名称改为全部,去除问题分类(统一为问题列表),增加社区文章列表
|
||||
* 游戏搜索默认页面改版
|
||||
* 权限系统更改,不授权也可以进去App,申请权限细分到功能(用到某个功能时才需要强制授予权限)
|
||||
* 增加隐私系统
|
||||
* 增加游戏预约功能
|
||||
* 增加标签详情模块
|
||||
* 进入今日头条广告SDK
|
||||
* 图片上传压缩机制优化
|
||||
- 支持从后台修改上传配置(本该在早些版本实现,由于代码问题无法引用后台配置)
|
||||
- 对压缩失败是进行catch(由于后台对宽高配置放宽,很容易发生OOM),失败后直接上传原图(这步可能会出现问题)
|
||||
* 游戏相关UI修改
|
||||
15
Dockerfile
15
Dockerfile
@ -1,15 +0,0 @@
|
||||
FROM openjdk:11-jdk
|
||||
WORKDIR /project
|
||||
SHELL ["/bin/bash", "-c"]
|
||||
#配置SDK环境变量
|
||||
ENV ANDROID_SDK_ROOT /usr/lib/sdk
|
||||
ENV ANDROID_HOME /usr/lib/sdk
|
||||
ENV PATH $ANDROID_SDK_ROOT:$PATH
|
||||
ENV PATH=$PATH:${ANDROID_HOME}/cmdline-tools/cmdline-tools/bin/
|
||||
ENV GRADLE_USER_HOME /project/.gradle
|
||||
RUN source ~/.bashrc
|
||||
RUN sed -i "s@http://\(deb\|security\).debian.org@https://mirrors.aliyun.com@g" /etc/apt/sources.list \
|
||||
&& apt-get --quiet update --yes \
|
||||
&& apt-get --quiet install --yes lib32stdc++6 lib32z1 libncurses5 util-linux bash tzdata librdkafka-dev pkgconf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY .gradle /project/.gradle
|
||||
47
README.md
47
README.md
@ -1,47 +0,0 @@
|
||||
# 光环助手Android客户端
|
||||
|
||||
### 概述
|
||||
|
||||
光环助手Android客户端目前使用 Kotlin 作为主要开发语言,以 MVVM 作为参考架构模式进行开发
|
||||
|
||||
### 约束
|
||||
|
||||
为编写易读易维护且较健壮的代码,可参考以下约束
|
||||
|
||||
1. 尽量将逻辑代码放置于 ViewModel 中,View 中只执行 UI 操作
|
||||
2. 尽量使 View 在被销毁之后仍能恢复状态,处理方式可参考 [保存界面状态](https://developer.android.com/topic/libraries/architecture/saving-states)
|
||||
3. 尽量参考原有文件结构及命名规范,即以 大模块 - 小模块 的形式生成包关系
|
||||
4. 遵循最小改动原则,在提交代码前务必先检查变动的代码,尽量以可控的变动规模来构成一个 commit ,以便日后追踪问题
|
||||
5. Commit message 提交规范可参考 [Conventional Commits](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
|
||||
6. 代码规范可参考 [AOSP Java 风格](https://source.android.com/setup/contribute/code-style)
|
||||
7. 尽量使用 Kotlin 来写新文件
|
||||
8. 不要使用 DataBinding
|
||||
9. Commit 前请确保不带入非项目必须文件,可手动修改 [.gitignore](https://stackoverflow.com/questions/8527597/how-do-i-ignore-files-in-a-directory-in-git) 文件忽略
|
||||
10. 优先使用 ViewBinding 获取 View 对象
|
||||
11. No AsyncTask!
|
||||
|
||||
### 公用部分
|
||||
|
||||
本项目使用 LiveData 实现了一个简单通用的基础列表分页功能,具体可见 `ListFragment`, `ListViewModel` 等类,理想情况下只需少量代码即可新建一个简单分页列表
|
||||
|
||||
### 首次拉取项目代码
|
||||
|
||||
`git clone -b dev git@git.shanqu.cc:halo/android/assistant-android.git --recursive`
|
||||
|
||||
### git 版本管理
|
||||
|
||||
本项目使用简化版的 git flow 来管理分支,细节请看 [光环安卓简单 git 规范](https://git.shanqu.cc/halo/android/assistant-android/-/wikis/%E5%85%89%E7%8E%AF%E5%AE%89%E5%8D%93%E7%AE%80%E5%8D%95-git-%E8%A7%84%E8%8C%83)
|
||||
|
||||
### 图片资源配置
|
||||
|
||||
* 新增图片资源时,默认只添加最高规格的 xxxhdpi 文件
|
||||
* 新增图片资源时,需要将其转换为 .webp 格式 (包括含透明图层的图片,默认质量为90%) (转换后体积变大的文件除外)
|
||||
|
||||
### 第三方appkey等配置
|
||||
|
||||
* 修改 `gradle.properties` 文件将各种key填入其中,实现统一管理
|
||||
* 通过 gradle 文件内的 resValue/buildConfigField/manifestPlaceHolder 方式实现编译期间修改,具体情况请参考 ``./build.gradle`` 和 ``./app/build.gradle`` 配置
|
||||
|
||||
### 混淆配置
|
||||
|
||||
* 本项目默认使用 R8 作为混淆工具,往 proguard-rules.txt 添加 proguard 新配置项时请检查可用性(如语法等)
|
||||
736
app/build.gradle
736
app/build.gradle
@ -1,685 +1,113 @@
|
||||
// This comment exists for a reason, do not delete
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android' // kotlin
|
||||
apply plugin: 'kotlin-parcelize'
|
||||
apply plugin: 'com.google.devtools.ksp'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'therouter'
|
||||
|
||||
import groovy.xml.XmlUtil
|
||||
task('processWithJavassist') << {
|
||||
String classPath = file('build/intermediates/classes/debug')//项目编译class所在目录
|
||||
dodola.patch.PatchClass.process(classPath, project(':hackdex').buildDir
|
||||
.absolutePath + '/intermediates/classes/debug')//第二个参数是hackdex的class所在目录
|
||||
}
|
||||
|
||||
task buildJar(dependsOn: ['compileReleaseJavaWithJavac'], type: Jar) {
|
||||
|
||||
baseName = "news"
|
||||
//后缀名
|
||||
extension = "jar"
|
||||
//最终的 Jar 包名,如果没设置,默认为 [baseName]-[appendix]-[version]-[classifier].[extension]
|
||||
archiveName = "news.jar";
|
||||
|
||||
//需打包的资源所在的路径集
|
||||
def srcClassDir = [project.buildDir.absolutePath + "/intermediates/classes/debug"];
|
||||
from srcClassDir
|
||||
|
||||
//去除路径集下部分的资源
|
||||
exclude "com/gh/gamecenter/BuildConfig.class"
|
||||
exclude "com/gh/gamecenter/R.class"
|
||||
exclude "com/gh/gamecenter/BuildConfig/\$*.class"
|
||||
exclude "com/gh/gamecenter/R/\$*.class"
|
||||
|
||||
//只导入资源路径集下的部分资源
|
||||
include "com/gh/gamecenter/NewsActivity.class"
|
||||
include "com/gh/gamecenter/NewsActivity\$*.class"
|
||||
//注: exclude include 支持可变长参数
|
||||
}
|
||||
|
||||
android {
|
||||
|
||||
String CONFIG_ID = ""
|
||||
String FIRST_LAUNCH = ""
|
||||
String SDK_VERSION = ""
|
||||
String SDK_APP_ID = ""
|
||||
String SDK_APP_NAME = ""
|
||||
boolean USE_DEFAULT_CHANNEL_SDK = true
|
||||
int ACTIVATE_REPORTING_RATIO = 100
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
dataBinding true
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
dexOptions {
|
||||
// jumboMode = true
|
||||
javaMaxHeapSize "4g"
|
||||
preDexLibraries true
|
||||
maxProcessCount 8
|
||||
}
|
||||
|
||||
aaptOptions {
|
||||
additionalParameters "--no-version-vectors"
|
||||
}
|
||||
|
||||
kapt {
|
||||
useBuildCache = true
|
||||
javacOptions {
|
||||
// 增加注解处理器的最大错误次数,默认为 100
|
||||
option("-Xmaxerrs", 500)
|
||||
}
|
||||
}
|
||||
|
||||
ksp {
|
||||
arg("ROUTER_MODULE_NAME", project.getName())
|
||||
}
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "23.0.3"
|
||||
|
||||
defaultConfig {
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
multiDexEnabled true
|
||||
applicationId "com.gh.gamecenter"
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 19
|
||||
versionCode 14
|
||||
versionName "1.51"
|
||||
|
||||
ndk {
|
||||
// x86 本来是为了模拟器用户使用 RenderScript 用的,但是其实用到 RenderScript 的人本来就不多 (一天不到 100),用模拟器的人就更少了
|
||||
// 加了 x86 反而会导致用户没法使用微博登录,因为微博没有提供 x86 的 SO ...
|
||||
// 还会增大 APK 体积,所以还是去掉吧。数据可见 https://sentry.shanqu.cc/organizations/lightgame/issues/144232/?project=22
|
||||
abiFilters "armeabi-v7a", "arm64-v8a"
|
||||
}
|
||||
|
||||
renderscriptTargetApi 18
|
||||
renderscriptSupportModeEnabled true
|
||||
|
||||
// 由于app只针对中文用户,所以仅保留zh资源,其他删掉
|
||||
resConfigs "zh"
|
||||
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode rootProject.ext.versionCode
|
||||
versionName rootProject.ext.versionName
|
||||
applicationId rootProject.ext.applicationId
|
||||
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt', 'proguard-fresco.txt', rootProject.ext.va_proguard_rules
|
||||
|
||||
String CORE_EVENT_GAME_CATEGORY = ""
|
||||
|
||||
// 推广用的关键事件游戏类型
|
||||
buildConfigField "String", "CORE_EVENT_GAME_CATEGORY", "\"${CORE_EVENT_GAME_CATEGORY}\""
|
||||
|
||||
// 推广用的配置 id
|
||||
buildConfigField "String", "CONFIG_ID", "\"${CONFIG_ID}\""
|
||||
|
||||
// 推广用的 SDK 版本 (仅记录使用)
|
||||
buildConfigField "String", "SDK_VERSION", "\"${SDK_VERSION}\""
|
||||
buildConfigField "String", "SDK_APP_ID", "\"${SDK_APP_ID}\""
|
||||
buildConfigField "String", "SDK_APP_NAME", "\"${SDK_APP_NAME}\""
|
||||
buildConfigField "boolean", "USE_DEFAULT_CHANNEL_SDK", "${USE_DEFAULT_CHANNEL_SDK}"
|
||||
|
||||
// 首次启动的跳转配置
|
||||
buildConfigField "String", "FIRST_LAUNCH", "\"${FIRST_LAUNCH}\""
|
||||
|
||||
buildConfigField "int", "ACTIVATE_REPORTING_RATIO", "${ACTIVATE_REPORTING_RATIO}"
|
||||
|
||||
// All third-party appid/appkey
|
||||
buildConfigField "boolean", "IS_GAT_APP", "false"
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "LOG_HUB_PROJECT", "\"${LOG_HUB_PROJECT}\""
|
||||
buildConfigField "String", "VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "WGAME_CPM_BUSIAPPID", "\"${WGAME_CPM_BUSIAPPID}\""
|
||||
buildConfigField "String", "WGAME_CPM_API_HOST", "\"${WGAME_CPM_API_HOST}\""
|
||||
buildConfigField "String", "WECHAT_APPID", "\"${WECHAT_APPID}\""
|
||||
buildConfigField "String", "WECHAT_SECRET", "\"${WECHAT_SECRET}\""
|
||||
buildConfigField "String", "TENCENT_APPID", "\"${TENCENT_APPID}\""
|
||||
buildConfigField "String", "WEIBO_APPKEY", "\"${WEIBO_APPKEY}\""
|
||||
buildConfigField "String", "DSP_API_HOST","\"${DSP_API_HOST}\""
|
||||
// 一体包的32位畅玩游戏助手包名
|
||||
buildConfigField "String", "EXT_PACKAGE_NAME", "\"${rootProject.ext.EXT_PACKAGE_NAME}\""
|
||||
// 默认的渠道
|
||||
// manifestPlaceholders = [CHANNEL_VALUE: "GH_TEST"]
|
||||
}
|
||||
|
||||
// gradle 2.2以上默认同时启用v1和v2(优先用于Android N)
|
||||
/**
|
||||
* 签名设置
|
||||
*/
|
||||
signingConfigs {
|
||||
debug {
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
release {
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
storeFile file("gh.keystore")
|
||||
keyAlias "gh.keystore"
|
||||
keyPassword "20150318"
|
||||
storePassword "20150318"
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
// exclude 部分冗余的文件
|
||||
exclude 'META-INF/gradle/incremental.annotation.processors'
|
||||
exclude 'darwin/x86_64/liblz4-java.dylib'
|
||||
|
||||
exclude 'assets/libwbsafeedit_x86'
|
||||
exclude 'assets/libwbsafeedit_x86_64'
|
||||
|
||||
exclude 'lib/armeabi-v7a/libRSSupport.so'
|
||||
exclude 'lib/arm64-v8a/libRSSupport.so'
|
||||
exclude 'lib/armeabi-v7a/librsjni.so'
|
||||
exclude 'lib/arm64-v8a/librsjni.so'
|
||||
|
||||
resources.excludes += "com/j256/*"
|
||||
resources.excludes += "org/apache/commons/codec/language/bm/*"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
debug {
|
||||
debuggable true
|
||||
minifyEnabled false
|
||||
zipAlignEnabled false
|
||||
signingConfig signingConfigs.debug
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
release {
|
||||
debuggable false
|
||||
minifyEnabled true
|
||||
zipAlignEnabled true
|
||||
shrinkResources true
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
buildConfigField "String", "EXPOSURE_REPO", "\"exposure\""
|
||||
buildConfigField "String", "EXPOSURE_VERSION", "\"E4\""
|
||||
|
||||
multiDexKeepProguard file("tinker_multidexkeep.pro")
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore useless variant
|
||||
variantFilter { variant ->
|
||||
def names = variant.flavors*.name
|
||||
def isDebugType = variant.buildType.name == "debug"
|
||||
if ((names.contains("tea") || name.contains("kuaishou") || name.contains("gdt")) && isDebugType) {
|
||||
setIgnore(true)
|
||||
}
|
||||
}
|
||||
|
||||
flavorDimensions("env", "region")
|
||||
|
||||
sourceSets {
|
||||
|
||||
debug {
|
||||
assets.srcDirs += 'src/main/assets-debug'
|
||||
}
|
||||
|
||||
release {
|
||||
assets.srcDirs += 'src/main/assets-release'
|
||||
}
|
||||
|
||||
publish {
|
||||
java.srcDirs = ['src/main/java', "src/default/java"]
|
||||
}
|
||||
internal {
|
||||
java.srcDirs = ['src/main/java', "src/default/java", "src/internal/java"]
|
||||
}
|
||||
tea {
|
||||
java.srcDirs = ['src/main/java', 'src/tea/java']
|
||||
}
|
||||
kuaishou {
|
||||
java.srcDirs = ['src/main/java', 'src/kuaishou/java']
|
||||
}
|
||||
gdt {
|
||||
java.srcDirs = ['src/main/java', 'src/gdt/java']
|
||||
}
|
||||
gat {
|
||||
java.srcDirs = ['src/main/java', 'src/gat/java']
|
||||
}
|
||||
cn {
|
||||
java.srcDirs = ['src/main/java', 'src/cn/java']
|
||||
}
|
||||
sm {
|
||||
java.srcDirs = ['src/main/java', 'src/sm/java']
|
||||
}
|
||||
}
|
||||
// applicationVariants.all { variant ->
|
||||
// variant.dex.dependsOn << processWithJavassist //在执行dx命令之前将代码打入到class中
|
||||
// }
|
||||
|
||||
/**
|
||||
* 渠道打包
|
||||
*/
|
||||
productFlavors {
|
||||
// internal, 内部测试包使用的 flavor,接口包含包括测试和正式环境
|
||||
internal {
|
||||
dimension "env"
|
||||
versionNameSuffix "-debug"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${DEV_API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_DEV_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${DEV_VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${DEV_QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${DEV_QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${DEV_CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}-debug\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}-debug")
|
||||
}
|
||||
|
||||
// publish, 发布时候使用的 flavor,接口仅包含正式环境
|
||||
publish {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
tea {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
|
||||
manifestPlaceholders.put("APPLOG_SCHEME", "rangersapplog.byAx6uYt".toLowerCase())
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
kuaishou {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
gdt {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
sm {
|
||||
dimension "env"
|
||||
|
||||
buildConfigField "String", "DEV_API_HOST", "\"${API_HOST}\""
|
||||
buildConfigField "String", "NEW_DEV_API_HOST", "\"${NEW_API_HOST}\""
|
||||
buildConfigField "String", "DEV_VAPI_HOST", "\"${VAPI_HOST}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPID", "\"${QUICK_LOGIN_APPID}\""
|
||||
buildConfigField "String", "QUICK_LOGIN_APPKEY", "\"${QUICK_LOGIN_APPKEY}\""
|
||||
buildConfigField "String", "DEV_CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
buildConfigField "String", "CSJ_APPID", "\"${CSJ_APPID}\""
|
||||
|
||||
buildConfigField "String", "VA_VERSION_NAME", "\"${rootProject.ext.VA_VERSION}\""
|
||||
manifestPlaceholders.put("VA_VERSION_NAME", "${rootProject.ext.VA_VERSION}")
|
||||
}
|
||||
|
||||
// 港澳台
|
||||
gat {
|
||||
dimension "region"
|
||||
|
||||
applicationId rootProject.ext.applicationIdGat
|
||||
|
||||
// 支持繁体
|
||||
resConfigs "zh", "zh-rTW"
|
||||
|
||||
buildConfigField "boolean", "IS_GAT_APP", "true"
|
||||
buildConfigField "String", "LOG_HUB_PROJECT", "\"${LOG_HUB_PROJECT_GAT}\""
|
||||
buildConfigField "String", "API_HOST", "\"${API_HOST_GAT}\""
|
||||
buildConfigField "String", "NEW_API_HOST", "\"${NEW_API_HOST_GAT}\""
|
||||
}
|
||||
|
||||
cn {
|
||||
dimension "region"
|
||||
}
|
||||
GH_100 {}
|
||||
GH_101 {}
|
||||
GH_102 {}
|
||||
GH_103 {}
|
||||
GH_104 {}
|
||||
GH_106 {}
|
||||
GH_109 {}
|
||||
GH_110 {}
|
||||
GH_113 {}
|
||||
GH_114 {}
|
||||
GH_115 {}
|
||||
GH_116 {}
|
||||
GH_118 {}
|
||||
GH_119 {}
|
||||
GH_120 {}
|
||||
GH_121 {}
|
||||
GH_123 {}
|
||||
GH_200 {}
|
||||
GH_201 {}
|
||||
GH_202 {}
|
||||
GH_203 {}
|
||||
GH_307 {}
|
||||
GH_127 {}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs 'libs', 'libs/aars'
|
||||
}
|
||||
}
|
||||
|
||||
// 删除不需要的 assets
|
||||
android.applicationVariants.configureEach { variant ->
|
||||
variant.mergeAssets.doLast {
|
||||
def assetDir = variant.mergeAssetsProvider.get().outputDir.get()
|
||||
def unwantedAssets = ['1832823466', 'gdt_plugin/gdtadv2.jar']
|
||||
|
||||
unwantedAssets.each { assetPath ->
|
||||
def file = new File([assetDir, assetPath].join(File.separator))
|
||||
if (file.exists()) {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
productFlavors.all { flavor ->
|
||||
flavor.manifestPlaceholders = [CHANNEL_VALUE: name]//命令 gradlew assembleRelease
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
|
||||
|
||||
teaImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/tea/libs')
|
||||
kuaishouImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/kuaishou/libs')
|
||||
gdtImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/gdt/libs')
|
||||
smImplementation fileTree(include: ['*.jar', '*.aar'], dir: 'src/sm/libs')
|
||||
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary}"
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android-process:${leakcanary}"
|
||||
|
||||
// debugImplementation "com.gu.android:toolargetool:${toolargetool}" // 需要使用调试时才启用
|
||||
debugImplementation "com.github.nichbar:WhatTheStack:${whatTheStack}"
|
||||
|
||||
implementation "androidx.multidex:multidex:${multiDex}"
|
||||
implementation "androidx.fragment:fragment-ktx:${fragment}"
|
||||
|
||||
implementation "androidx.annotation:annotation:${annotation}"
|
||||
|
||||
implementation "androidx.viewpager2:viewpager2:${viewpager2}"
|
||||
ksp("androidx.room:room-compiler:${room}")
|
||||
|
||||
implementation "com.tencent.vasdolly:helper:${apkChannelPackage}"
|
||||
implementation "com.tencent.vasdolly:writer:${apkChannelPackage}"
|
||||
|
||||
implementation "com.j256.ormlite:ormlite-android:${ormlite}"
|
||||
implementation "com.j256.ormlite:ormlite-core:${ormlite}"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
implementation "com.contrarywind:Android-PickerView:${pickerView}"
|
||||
|
||||
implementation "net.cachapa.expandablelayout:expandablelayout:${expandableLayout}"
|
||||
|
||||
// 用于比较 versionName 是大于小于或等于
|
||||
implementation "com.g00fy2:versioncompare:${versioncompare}"
|
||||
|
||||
// for video streaming
|
||||
implementation("com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-java:$gsyVideo", {
|
||||
exclude module: "gsyvideoplayer-androidvideocache"
|
||||
exclude group: "tv.danmaku.ijk.media"
|
||||
})
|
||||
implementation("com.github.CarGuo.GSYVideoPlayer:gsyVideoPlayer-exo_player2:$gsyVideo") {
|
||||
exclude group: 'com.google.android.exoplayer', module: 'extension-rtmp'
|
||||
}
|
||||
|
||||
implementation "com.llew.huawei:verifier:${verifier}"
|
||||
|
||||
teaImplementation "com.bytedance.applog:RangersAppLog-Lite-cn:${bytedanceApplog}"
|
||||
teaImplementation "com.bytedance.ads:AppConvert:${bytedanceAppConvert}"
|
||||
|
||||
implementation "net.lingala.zip4j:zip4j:${zip4j}"
|
||||
|
||||
implementation "com.github.hsiafan:apk-parser:${apkParser}"
|
||||
implementation "org.nanohttpd:nanohttpd:${nanohttpd}"
|
||||
|
||||
implementation "com.lg:easyfloat:${easyFloat}"
|
||||
|
||||
implementation("com.lg:apksig:${apksig}") {
|
||||
exclude group: 'com.google.protobuf'
|
||||
}
|
||||
|
||||
implementation "com.lg:gid:${gid}"
|
||||
|
||||
implementation "com.lg:shortcut:${shortcut}"
|
||||
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:${desugarJdkLibs}"
|
||||
|
||||
kapt "com.google.auto.service:auto-service:${autoServiceVersion}"
|
||||
ksp "cn.therouter:apt:${routerVersion}"
|
||||
|
||||
implementation project(':ndownload')
|
||||
implementation project(':vspace-bridge:vspace')
|
||||
implementation(project(':feature:xapk-installer'))
|
||||
|
||||
implementation(project(':module_common')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
implementation(project(':module_login')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
implementation(project(':module_core_feature')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
implementation(project(':module_setting')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
|
||||
// implementation(project(':module_setting_compose')) {
|
||||
// exclude group: 'androidx.swiperefreshlayout'
|
||||
// }
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enablePkg) {
|
||||
implementation(project(':feature:pkg'))
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableFeedback) {
|
||||
implementation(project(':feature:new_feedback')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableMessage) {
|
||||
implementation(project(':module_message')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableOaid) {
|
||||
implementation(project(':feature:oaid'))
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableFloatingWindow) {
|
||||
implementation(project(':feature:floating-window'))
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableSensorData) {
|
||||
implementation(project(':module_sensors_data')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableCsjAd) {
|
||||
implementation(project(':feature:csj_ad'))
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableQQGame) {
|
||||
implementation(project(':feature:qq_game')) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enablePush) {
|
||||
def pushProperty = findProperty('BUILD_PUSH_TYPE')
|
||||
// 根据BUILD_PUSH_TYPE决定使用哪个推送SDK,目前默认使用极光推送
|
||||
def pushProject = (pushProperty == null || pushProperty == 'jg')
|
||||
? project(':feature:jg_push') : project(':feature:acloud_push')
|
||||
|
||||
implementation(pushProject) {
|
||||
exclude group: 'androidx.swiperefreshlayout'
|
||||
}
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableSentry) {
|
||||
implementation(project(':feature:sentry'))
|
||||
}
|
||||
|
||||
if (gradle.ext.enableRouteDoc) {
|
||||
ksp project(":feature:route_doc")
|
||||
}
|
||||
|
||||
implementation(project(':feature:media_select'))
|
||||
|
||||
implementation(project(":module_va_api"))
|
||||
implementation(project(":va-archive-common"))
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableVa) {
|
||||
implementation(project(":module_va_impl"))
|
||||
}
|
||||
debugImplementation "com.bytedance.tools.codelocator:codelocator-core:2.0.3"
|
||||
internalImplementation(project(':module_internal_test'))
|
||||
|
||||
debugImplementation 'com.bytedance.android:shadowhook:1.0.9'
|
||||
debugImplementation 'io.github.shiqos:wytrace:1.0.1'
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableAccelerator) {
|
||||
implementation(project(":feature:accelerator"))
|
||||
}
|
||||
|
||||
if (!gradle.ext.excludeOptionalModules || gradle.ext.enableAliPay) {
|
||||
implementation(project(":feature:ali_pay"))
|
||||
}
|
||||
|
||||
if(!gradle.ext.excludeOptionalModules || gradle.ext.enableWechatPay){
|
||||
implementation(project(":feature:wechat_pay"))
|
||||
}
|
||||
|
||||
implementation "me.xdrop:fuzzywuzzy:${fuzzyVersion}"
|
||||
}
|
||||
|
||||
File propFile = file('sign.properties')
|
||||
if (propFile.exists()) {
|
||||
Properties props = new Properties()
|
||||
props.load(new FileInputStream(propFile))
|
||||
|
||||
if (props.containsKey('keyAlias') && props.containsKey('keyPassword') &&
|
||||
props.containsKey('storeFile') && props.containsKey('storePassword')) {
|
||||
android.signingConfigs {
|
||||
// debug 不要使用正式签名,这样tinker才不会打补丁。
|
||||
debug {
|
||||
keyAlias props.get('keyAlias')
|
||||
keyPassword props.get('keyPassword')
|
||||
storeFile file(props.get('storeFile'))
|
||||
storePassword props.get('storePassword')
|
||||
}
|
||||
release {
|
||||
keyAlias props.get('keyAlias')
|
||||
keyPassword props.get('keyPassword')
|
||||
storeFile file(props.get('storeFile'))
|
||||
storePassword props.get('storePassword')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
} else {
|
||||
android.buildTypes.release.signingConfig = null
|
||||
}
|
||||
|
||||
// 用于测试读取 META-INF 里的文件
|
||||
//task generateMetaJson {
|
||||
// def resDir = new File(buildDir, 'generated/FILES_FOR_META_INF/')
|
||||
// def destDir = new File(resDir, 'META-INF/')
|
||||
// // Add resDir as a resource directory so that it is automatically included in the APK.
|
||||
// android {
|
||||
// sourceSets {
|
||||
// main.resources {
|
||||
// srcDir resDir
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// doLast {
|
||||
// if (!destDir.exists()) destDir.mkdirs()
|
||||
// copy {
|
||||
// into destDir
|
||||
// from new File('generated/FILES_FOR_META_INF/META-INF/halo_skip.json')
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//// Specify when put_files_in_META_INF should run
|
||||
//project.afterEvaluate {
|
||||
// tasks.findAll { task ->
|
||||
// task.name.startsWith('merge') && task.name.endsWith('Resources')
|
||||
// }.each { t -> t.dependsOn generateMetaJson }
|
||||
//}
|
||||
|
||||
project.afterEvaluate {
|
||||
def variants = null
|
||||
try {
|
||||
variants = android.applicationVariants
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace()
|
||||
try {
|
||||
variants = android.libraryVariants
|
||||
} catch (Throwable tt) {
|
||||
tt.printStackTrace()
|
||||
}
|
||||
}
|
||||
if (variants != null) {
|
||||
variants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def task = output.processManifestProvider.get()
|
||||
if (task == null) {
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
* 为 Manifest 的 Activity 的 configChanges 添加自己手动处理 configurationChanges 配置 [https://developer.android.com/guide/topics/resources/runtime-changes]
|
||||
* AGP 4.1.0 从 ProcessManifest task 里拿 manifest 的 API 变更调整可以参考这里 [https://github.com/Tencent/tinker/pull/1476/commits/d71645729b13d545ca4ba6826f93fbf558751434]
|
||||
* (搞半天还是不会抽离方法,有空再把 gradle 改成用 kotlin 实现吧)
|
||||
*/
|
||||
task.doLast {
|
||||
def manifestFile = new File(multiApkManifestOutputDirectory.get().asFile, "AndroidManifest.xml")
|
||||
if (manifestFile == null || !manifestFile.exists()) {
|
||||
return
|
||||
}
|
||||
|
||||
String[] configChanges = [
|
||||
"density",
|
||||
"fontScale",
|
||||
"keyboard",
|
||||
"keyboardHidden",
|
||||
"layoutDirection",
|
||||
"locale",
|
||||
"mcc",
|
||||
"mnc",
|
||||
"navigation",
|
||||
"orientation",
|
||||
"screenLayout",
|
||||
"screenSize",
|
||||
"smallestScreenSize",
|
||||
"touchscreen",
|
||||
"uiMode"]
|
||||
|
||||
def parser = new XmlSlurper(false, true)
|
||||
def manifest = parser.parse(manifestFile)
|
||||
def app = manifest.'application'[0]
|
||||
app.'activity'.each { act ->
|
||||
String value = act.attributes()['android:configChanges']
|
||||
if (value == null || value.isEmpty()) {
|
||||
if (value == null) value = ""
|
||||
configChanges.eachWithIndex { config, index ->
|
||||
if (index != configChanges.length - 1) {
|
||||
value += config + "|"
|
||||
} else {
|
||||
value += config
|
||||
}
|
||||
}
|
||||
act.attributes()['androidconfigChanges'] = value
|
||||
} else {
|
||||
String[] valueSplit = value.split("\\|")
|
||||
println configChanges
|
||||
configChanges.eachWithIndex { config, index ->
|
||||
if (!valueSplit.contains(config)) {
|
||||
value += ("|" + config)
|
||||
}
|
||||
}
|
||||
act.attributes()['android:configChanges'] = value
|
||||
}
|
||||
}
|
||||
|
||||
def tmpManifest = XmlUtil.serialize(manifest).replaceAll("androidconfigChanges", "android:configChanges")
|
||||
manifest = parser.parseText(tmpManifest)
|
||||
manifestFile.setText(XmlUtil.serialize(manifest), "utf-8")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
testCompile 'junit:junit:4.12'
|
||||
compile 'pl.droidsonroids.gif:android-gif-drawable:1.1.16'
|
||||
}
|
||||
BIN
app/libs/EventBus-2.4.0.jar
Normal file
BIN
app/libs/EventBus-2.4.0.jar
Normal file
Binary file not shown.
BIN
app/libs/MiPush_SDK_Client_2_2_18.jar
Normal file
BIN
app/libs/MiPush_SDK_Client_2_2_18.jar
Normal file
Binary file not shown.
BIN
app/libs/MobCommons-2016.0426.1819.jar
Normal file
BIN
app/libs/MobCommons-2016.0426.1819.jar
Normal file
Binary file not shown.
BIN
app/libs/MobTools-2016.0426.1819.jar
Normal file
BIN
app/libs/MobTools-2016.0426.1819.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-Core-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-Core-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-QQ-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-QQ-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-QZone-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-QZone-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-SinaWeibo-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-SinaWeibo-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-Wechat-Core-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-Wechat-Core-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/ShareSDK-Wechat-Moments-2.7.2.jar
Normal file
BIN
app/libs/ShareSDK-Wechat-Moments-2.7.2.jar
Normal file
Binary file not shown.
BIN
app/libs/TalkingDataAnalytics_V1.2.79.jar
Normal file
BIN
app/libs/TalkingDataAnalytics_V1.2.79.jar
Normal file
Binary file not shown.
BIN
app/libs/alicloud-android-sdk-httpdns-1.0.6.jar
Normal file
BIN
app/libs/alicloud-android-sdk-httpdns-1.0.6.jar
Normal file
Binary file not shown.
BIN
app/libs/android-support-v4.jar
Normal file
BIN
app/libs/android-support-v4.jar
Normal file
Binary file not shown.
BIN
app/libs/android-support-v7-appcompat.jar
Normal file
BIN
app/libs/android-support-v7-appcompat.jar
Normal file
Binary file not shown.
BIN
app/libs/gson-2.3.1.jar
Normal file
BIN
app/libs/gson-2.3.1.jar
Normal file
Binary file not shown.
BIN
app/libs/mid-sdk-2.3.jar
Normal file
BIN
app/libs/mid-sdk-2.3.jar
Normal file
Binary file not shown.
BIN
app/libs/mta-android-stat-sdk-2.2.0_20160504.jar
Normal file
BIN
app/libs/mta-android-stat-sdk-2.2.0_20160504.jar
Normal file
Binary file not shown.
BIN
app/libs/ormlite-android-4.49-SNAPSHOT.jar
Normal file
BIN
app/libs/ormlite-android-4.49-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
app/libs/ormlite-core-4.49-SNAPSHOT.jar
Normal file
BIN
app/libs/ormlite-core-4.49-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
app/libs/universal-image-loader-1.9.4.jar
Normal file
BIN
app/libs/universal-image-loader-1.9.4.jar
Normal file
Binary file not shown.
BIN
app/libs/utdid4all-1.0.4.jar
Normal file
BIN
app/libs/utdid4all-1.0.4.jar
Normal file
Binary file not shown.
@ -1,21 +0,0 @@
|
||||
# Keep our interfaces so they can be used by other ProGuard rules.
|
||||
# See http://sourceforge.net/p/proguard/bugs/466/
|
||||
-keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
|
||||
|
||||
# Do not strip any method/class that is annotated with @DoNotStrip
|
||||
-keep @com.facebook.common.internal.DoNotStrip class *
|
||||
-keepclassmembers class * {
|
||||
@com.facebook.common.internal.DoNotStrip *;
|
||||
}
|
||||
|
||||
# Keep native methods
|
||||
-keepclassmembers class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-dontwarn okio.**
|
||||
-dontwarn com.squareup.okhttp.**
|
||||
-dontwarn okhttp3.**
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn com.android.volley.toolbox.**
|
||||
-dontwarn com.facebook.infer.**
|
||||
17
app/proguard-rules.pro
vendored
Normal file
17
app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in C:\Android\sdk/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
@ -1,100 +0,0 @@
|
||||
|
||||
# inline getter method
|
||||
-allowaccessmodification
|
||||
|
||||
# TODO Dicard sourceFile in final release build but remain in internal build.
|
||||
-renamesourcefileattribute SourceFile
|
||||
# Keep Attribute
|
||||
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod,SourceFile,LineNumberTable
|
||||
|
||||
# OrmLite
|
||||
-keep class com.j256.*
|
||||
-keepclassmembers class com.j256.* { *; }
|
||||
-keep enum com.j256.*
|
||||
-keepclassmembers enum com.j256.* { *; }
|
||||
-keep interface com.j256.*
|
||||
-keepclassmembers interface com.j256.* { *; }
|
||||
-dontwarn com.j256.**
|
||||
|
||||
### app models
|
||||
-keep class com.gh.gamecenter.db.info.* {*;}
|
||||
-keep class com.gh.gamecenter.entity.** {<fields>;}
|
||||
-keep class com.gh.gamecenter.qa.entity.** {<fields>;}
|
||||
-keep class com.gh.gamecenter.gamedetail.entity.** {<fields>;}
|
||||
-keep class com.gh.download.DownloadDataSimpleEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.floatingwindow.FloatingWindowEntity {<fields>;}
|
||||
-keep class com.gh.gamecenter.BR
|
||||
-keep class com.gh.gamecenter.retrofit.* {*;}
|
||||
-keep class com.gh.gamecenter.eventbus.* {*;}
|
||||
-keep class com.gh.gamecenter.home.gamecollection.carousel.GameCollectionStackLayout {*;}
|
||||
-keep class com.gh.gamecenter.home.gamecollection.carousel.GameCollectionStackAnimation {*;}
|
||||
|
||||
# Prevent R8 from leaving Data object members always null
|
||||
-keepclassmembers,allowobfuscation class * {
|
||||
@com.google.gson.annotations.SerializedName <fields>;
|
||||
}
|
||||
|
||||
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
|
||||
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
|
||||
-keep class * extends com.google.gson.TypeAdapter
|
||||
-keep class * implements com.google.gson.TypeAdapterFactory
|
||||
-keep class * implements com.google.gson.JsonSerializer
|
||||
-keep class * implements com.google.gson.JsonDeserializer
|
||||
|
||||
# Retain generic signatures of TypeToken and its subclasses with R8 version 3.0 and higher.
|
||||
-keep,allowobfuscation,allowshrinking class com.google.gson.reflect.TypeToken
|
||||
-keep,allowobfuscation,allowshrinking class * extends com.google.gson.reflect.TypeToken
|
||||
|
||||
# TODO What's this ?
|
||||
-ignorewarnings
|
||||
|
||||
### 视频相关
|
||||
-keep class com.shuyu.gsyvideoplayer.video.* { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.video.**
|
||||
-keep class com.shuyu.gsyvideoplayer.video.base.* { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.video.base.**
|
||||
-keep class com.shuyu.gsyvideoplayer.utils.* { *; }
|
||||
-dontwarn com.shuyu.gsyvideoplayer.utils.**
|
||||
-keep class tv.danmaku.ijk.* { *; }
|
||||
-dontwarn tv.danmaku.ijk.**
|
||||
-keep public class * extends android.view.View {
|
||||
*** get*();
|
||||
void set*(***);
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
}
|
||||
|
||||
### RecyclerView.jumpToPositionForSmoothScroller
|
||||
-keep class androidx.recyclerview.widget.RecyclerView {
|
||||
void jumpToPositionForSmoothScroller(int);
|
||||
}
|
||||
|
||||
### ViewBinding 反射相关
|
||||
-keep class * implements androidx.viewbinding.ViewBinding {
|
||||
public static *** inflate(android.view.LayoutInflater, android.view.ViewGroup, boolean);
|
||||
}
|
||||
|
||||
### TEA
|
||||
-keep class com.gh.gamecenter.TeaHelper { *; }
|
||||
-keep class com.bytedance.ads.convert.broadcast.common.EncryptionTools {*;}
|
||||
|
||||
### EasyFloat
|
||||
-keep class com.lzf.easyfloat.* {*;}
|
||||
|
||||
### 广点通SDK
|
||||
-dontwarn com.qq.gdt.action.**
|
||||
-keep class com.qq.gdt.action.** {*;}
|
||||
-keep public class com.tencent.turingfd.sdk.**
|
||||
|
||||
### 神马 SDK
|
||||
-dontwarn com.gism.**
|
||||
|
||||
-keepclasseswithmembers class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
-keepclassmembernames class com.contrarywind.view.WheelView {
|
||||
private int itemsVisible;
|
||||
}
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
storeFile=gh.keystore
|
||||
storePassword=20150318
|
||||
keyAlias=gh.keystore
|
||||
keyPassword=20150318
|
||||
@ -0,0 +1,13 @@
|
||||
package com.gh.gamecenter;
|
||||
|
||||
import android.app.Application;
|
||||
import android.test.ApplicationTestCase;
|
||||
|
||||
/**
|
||||
* <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
|
||||
*/
|
||||
public class ApplicationTest extends ApplicationTestCase<Application> {
|
||||
public ApplicationTest() {
|
||||
super(Application.class);
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
package com.gh.gamecenter.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.common.constant.Config
|
||||
import com.gh.gamecenter.common.constant.Constants
|
||||
import com.gh.gamecenter.common.utils.PackageFlavorHelper
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.tencent.vasdolly.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
override fun getChannelStr(application: Application): String {
|
||||
var channel = ChannelReaderUtil.getChannel(application)
|
||||
if (channel == null || TextUtils.isEmpty(channel.trim())) {
|
||||
channel = if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
Config.DEFAULT_CHANNEL
|
||||
} else {
|
||||
Config.DEFAULT_CHANNEL_FOR_RELEASE
|
||||
}
|
||||
}
|
||||
if (PackageFlavorHelper.IS_TEST_FLAVOR) {
|
||||
channel = SPUtils.getString(Constants.SP_TEST_FLAVOR_CHANNEL, channel)
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun logEvent(content: String) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.app.Application
|
||||
import com.lightgame.utils.Utils
|
||||
import com.qq.gdt.action.ActionParam
|
||||
import com.qq.gdt.action.ActionType
|
||||
import com.qq.gdt.action.GDTAction
|
||||
import com.qq.gdt.action.PrivateController
|
||||
import org.json.JSONObject
|
||||
|
||||
object GdtHelper {
|
||||
private const val USER_ACTION_SET_ID = "1201041887"
|
||||
private const val APP_SECRET_ID = "c29cc5c48cf540c43b4b97363bb09216"
|
||||
|
||||
private const val KS_USER_ACTION_SET_ID = "1201032128"
|
||||
private const val KS_APP_SECRET_ID = "9bdbbb81d4e0bd333a2a581f9ee36986"
|
||||
|
||||
@JvmStatic
|
||||
fun init(application: Application, channel: String) {
|
||||
GDTAction.setPrivateController(object : PrivateController() {
|
||||
override fun isCanUsePhoneState(): Boolean {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
if (channel == "KS_GDT_GHZS_MC01") {
|
||||
GDTAction.init(application, KS_USER_ACTION_SET_ID, KS_APP_SECRET_ID, channel)
|
||||
} else {
|
||||
GDTAction.init(application, USER_ACTION_SET_ID, APP_SECRET_ID, channel)
|
||||
}
|
||||
|
||||
GDTAction.start()
|
||||
|
||||
Utils.log("init GdtHelper")
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun logAction(type: String) {
|
||||
when (type) {
|
||||
"EVENT_ACTIVE" -> GDTAction.logAction(ActionType.START_APP)
|
||||
"active_register" -> GDTAction.logAction(ActionType.REGISTER)
|
||||
"EVENT_NEXTDAY_STAY" -> GDTAction.logAction(ActionType.START_APP, JSONObject().apply {
|
||||
put(ActionParam.Key.LENGTH_OF_STAY, 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
package com.gh.gamecenter.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.GdtHelper
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.tencent.vasdolly.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
GdtHelper.init(application, getChannelStr(application))
|
||||
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
logEvent("EVENT_ACTIVE")
|
||||
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
|
||||
} else {
|
||||
val shouldSendRetentionLogEvent =
|
||||
SPUtils.getBoolean("SHOULD_SEND_RETENTION_EVENT", true)
|
||||
val installTimeNotToday =
|
||||
!TimeUtils.isToday(SPUtils.getLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000))
|
||||
if (shouldSendRetentionLogEvent && installTimeNotToday) {
|
||||
logEvent("EVENT_NEXTDAY_STAY")
|
||||
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChannelStr(application: Application): String {
|
||||
var channel = ChannelReaderUtil.getChannel(application)
|
||||
if (channel == null || TextUtils.isEmpty(channel.trim())) {
|
||||
channel = GDT_DEFAULT_CHANNEL
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
override fun logEvent(content: String) {
|
||||
GdtHelper.logAction(content)
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val GDT_DEFAULT_CHANNEL = "GDT_GHZS_01"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@ -1,42 +0,0 @@
|
||||
package com.gh.vspace
|
||||
|
||||
import android.content.Intent
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.Keep
|
||||
import com.gh.gamecenter.R
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.gh.gamecenter.databinding.LayoutPersonalOtherItemBinding
|
||||
import com.gh.vspace.installexternalgames.InstallExternalGameActivity
|
||||
import com.lightgame.utils.Utils
|
||||
import java.io.File
|
||||
|
||||
@Keep
|
||||
class ExternalGameUsage : ITestCase {
|
||||
|
||||
private fun buttonTemplate(viewParent: ViewGroup, id: Int, fn: (LayoutPersonalOtherItemBinding) -> Unit) {
|
||||
val context = viewParent.context
|
||||
viewParent.findViewById<View>(id) ?: run {
|
||||
val binding = LayoutPersonalOtherItemBinding.inflate(LayoutInflater.from(context)).apply {
|
||||
root.id = id
|
||||
fn(this)
|
||||
}
|
||||
viewParent.addView(binding.root, 0)
|
||||
}
|
||||
}
|
||||
|
||||
override fun addInstallExternalGameButton(viewParent: ViewGroup) {
|
||||
val context = viewParent.context
|
||||
buttonTemplate(viewParent, R.id.install_game_from_external) {
|
||||
it.titleTv.text = context.getString(R.string.title_install_external_game)
|
||||
it.iconIv.setImageResource(R.drawable.ic_personal_my_game)
|
||||
it.root.setOnClickListener {
|
||||
context.startActivity(
|
||||
InstallExternalGameActivity.getIntent(context)
|
||||
.apply { flags = flags or Intent.FLAG_ACTIVITY_NEW_TASK })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames;
|
||||
|
||||
public class Constants {
|
||||
public static final String TAG = "从SD卡安装";
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.common.utils.goneIf
|
||||
import com.gh.gamecenter.common.utils.toBinding
|
||||
|
||||
class ExternalGameAdapter(private val games: List<ExternalGameUiState>, private val onItemClickListener: OnItemClickListener) :
|
||||
RecyclerView.Adapter<ExternalGameViewHolder>() {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ExternalGameViewHolder {
|
||||
return ExternalGameViewHolder(parent.toBinding())
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return games.size
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ExternalGameViewHolder, position: Int) {
|
||||
val item = games[position]
|
||||
holder.apkInfo.text = item.externalGameEntity.let { item ->
|
||||
"""
|
||||
应用程序名:${item.appName}
|
||||
版本号:${item.apkVersion}
|
||||
包名: ${item.apkPackageName}
|
||||
路径:${item.apkPath}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
holder.update.setOnClickListener {
|
||||
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
|
||||
}
|
||||
|
||||
holder.install.goneIf(item.isInstalled) {
|
||||
holder.install.setOnClickListener {
|
||||
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_INSTALL)
|
||||
}
|
||||
}
|
||||
holder.uninstall.goneIf(!item.isInstalled) {
|
||||
holder.uninstall.setOnClickListener {
|
||||
onItemClickListener.onItemClick(
|
||||
item,
|
||||
OnItemClickListener.ClickType.CLICK_UNINSTALL
|
||||
)
|
||||
}
|
||||
}
|
||||
holder.start.goneIf(!item.isInstalled) {
|
||||
holder.start.setOnClickListener {
|
||||
onItemClickListener.onItemClick(item, OnItemClickListener.ClickType.CLICK_START)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
data class ExternalGameEntity(
|
||||
val cpuAbi: Set<String>,
|
||||
val apkPath: String,
|
||||
val apkFileName: String,
|
||||
val appName: String,
|
||||
val apkVersion: String,
|
||||
val apkPackageName: String,
|
||||
val lastModified: Long,
|
||||
)
|
||||
@ -1,6 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
data class ExternalGameUiState(
|
||||
val externalGameEntity: ExternalGameEntity,
|
||||
val isInstalled: Boolean
|
||||
)
|
||||
@ -1,12 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.gh.gamecenter.databinding.LayoutExternalGameItemBinding
|
||||
|
||||
class ExternalGameViewHolder(binding: LayoutExternalGameItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||
val apkInfo = binding.apkFileInfo
|
||||
val install = binding.btnInstall
|
||||
val uninstall = binding.btnUninstall
|
||||
val start = binding.btnStart
|
||||
val update = binding.btnUpdate
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import com.gh.gamecenter.common.base.activity.ToolBarActivity
|
||||
|
||||
class InstallExternalGameActivity : ToolBarActivity() {
|
||||
companion object {
|
||||
fun getIntent(context: Context): Intent {
|
||||
return getTargetIntent(context, InstallExternalGameActivity::class.java, InstallExternalGameFragment::class.java, Bundle())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,231 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Dialog
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment
|
||||
import android.provider.Settings
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.gh.common.util.DialogUtils
|
||||
import com.gh.gamecenter.common.base.fragment.ToolbarFragment
|
||||
import com.gh.gamecenter.common.exposure.meta.MetaUtil
|
||||
import com.gh.gamecenter.common.utils.dip2px
|
||||
import com.gh.gamecenter.common.utils.toColor
|
||||
import com.gh.gamecenter.common.utils.viewModelProvider
|
||||
import com.gh.gamecenter.common.view.divider.HorizontalDividerItemDecoration
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.databinding.FragmentInstallExternalGamesBinding
|
||||
import com.gh.vspace.VHelper
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.lg.vspace.VirtualAppManager
|
||||
import com.lightgame.download.DownloadEntity
|
||||
import io.reactivex.Single
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
|
||||
class InstallExternalGameFragment : ToolbarFragment(), OnItemClickListener {
|
||||
|
||||
private val mViewModel: InstallExternalGameViewModel by lazy { viewModelProvider() }
|
||||
|
||||
private lateinit var mBinding: FragmentInstallExternalGamesBinding
|
||||
|
||||
private val games = mutableListOf<ExternalGameUiState>()
|
||||
private var adapter = ExternalGameAdapter(games, this)
|
||||
|
||||
private var uninstallDisposable: Disposable? = null
|
||||
|
||||
|
||||
private var shouldScan = false
|
||||
|
||||
override fun getLayoutId() = 0
|
||||
|
||||
override fun getInflatedLayout() =
|
||||
FragmentInstallExternalGamesBinding.inflate(layoutInflater).apply { mBinding = this }.root
|
||||
|
||||
private lateinit var dialog: Dialog
|
||||
|
||||
|
||||
private val requestPermissionLauncher = registerForActivityResult<String, Boolean>(
|
||||
ActivityResultContracts.RequestPermission()
|
||||
) { result ->
|
||||
if (result == true) {
|
||||
// grant
|
||||
mViewModel.scanPaths()
|
||||
} else {
|
||||
// not grant
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setNavigationTitle(getString(com.gh.gamecenter.R.string.title_install_external_game))
|
||||
initView()
|
||||
mViewModel.gamesList.observe(this) {
|
||||
if (dialog.isShowing) {
|
||||
dialog.dismiss()
|
||||
}
|
||||
games.clear()
|
||||
games.addAll(
|
||||
it.map {
|
||||
ExternalGameUiState(it, VHelper.isInstalled(it.apkPackageName))
|
||||
}
|
||||
)
|
||||
adapter.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
if (!Environment.isExternalStorageManager()) {
|
||||
shouldScan = true
|
||||
AlertDialog.Builder(requireContext()).setMessage("请在设置页面允许光环助手")
|
||||
.setNegativeButton("去") { dialog, which ->
|
||||
val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
startActivity(intent)
|
||||
}.show()
|
||||
} else {
|
||||
mViewModel.scanPaths()
|
||||
}
|
||||
} else {
|
||||
requestStoragePermission()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private fun requestStoragePermission() {
|
||||
when {
|
||||
ContextCompat.checkSelfPermission(
|
||||
requireContext(),
|
||||
Manifest.permission.READ_EXTERNAL_STORAGE
|
||||
) == PackageManager.PERMISSION_GRANTED -> {
|
||||
mViewModel.scanPaths()
|
||||
}
|
||||
|
||||
shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> {
|
||||
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
|
||||
else -> {
|
||||
requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (shouldScan) {
|
||||
mViewModel.scanPaths()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
dialog = DialogUtils.showWaitDialog(requireContext(), "")
|
||||
mBinding.externalGamesList.let {
|
||||
it.adapter = adapter
|
||||
it.layoutManager = LinearLayoutManager(requireContext())
|
||||
val itemDecoration = HorizontalDividerItemDecoration.Builder(requireContext())
|
||||
.size(2F.dip2px())
|
||||
.color(com.gh.gamecenter.common.R.color.ui_divider.toColor(requireContext()))
|
||||
.build()
|
||||
if (it.itemDecorationCount != 0) {
|
||||
it.removeItemDecorationAt(0)
|
||||
}
|
||||
it.addItemDecoration(itemDecoration)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (dialog.isShowing) {
|
||||
dialog.dismiss()
|
||||
}
|
||||
if (uninstallDisposable?.isDisposed != true) {
|
||||
uninstallDisposable?.dispose()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: OnItemClickListener.ClickType) {
|
||||
when (clickType) {
|
||||
OnItemClickListener.ClickType.CLICK_INSTALL -> {
|
||||
install(externalGameUiState)
|
||||
}
|
||||
|
||||
OnItemClickListener.ClickType.CLICK_UNINSTALL -> {
|
||||
uninstall(externalGameUiState)
|
||||
}
|
||||
|
||||
OnItemClickListener.ClickType.CLICK_START -> {
|
||||
start(externalGameUiState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun install(externalGameUiState: ExternalGameUiState) {
|
||||
|
||||
VHelper.disableLaunchGameAfterInstallation()
|
||||
VHelper.install(requireContext(), DownloadEntity().apply {
|
||||
externalGameUiState.externalGameEntity.apply {
|
||||
packageName = apkPackageName
|
||||
path = apkPath
|
||||
}
|
||||
}, true)
|
||||
|
||||
VHelper.newCwValidateVspaceBeforeAction(
|
||||
requireContext(), null,
|
||||
) {
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun uninstall(externalGameUiState: ExternalGameUiState) {
|
||||
dialog.show()
|
||||
uninstallDisposable = Single.create<Void> {
|
||||
VHelper.uninstall(externalGameUiState.externalGameEntity.apkPackageName)
|
||||
}.subscribeOn(Schedulers.from(AppExecutor.lightWeightIoExecutor)).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe { t1, t2 ->
|
||||
if (dialog.isShowing) {
|
||||
dialog.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun start(externalGameUiState: ExternalGameUiState) {
|
||||
val intent = VirtualAppManager.get().getStartGameIntent(
|
||||
externalGameUiState.externalGameEntity.apkPackageName,
|
||||
"",
|
||||
externalGameUiState.externalGameEntity.appName,
|
||||
"",
|
||||
MetaUtil.getBase64EncodedAndroidId(),
|
||||
HaloApp.getInstance().gid,
|
||||
com.gh.gamecenter.BuildConfig.VERSION_NAME,
|
||||
HaloApp.getInstance().channel,
|
||||
"",
|
||||
"",
|
||||
com.gh.gamecenter.BuildConfig.VA_VERSION_NAME,
|
||||
HaloApp.getInstance().oaid
|
||||
)
|
||||
intent.setComponent(
|
||||
ComponentName(
|
||||
com.gh.gamecenter.BuildConfig.APPLICATION_ID,
|
||||
VirtualAppManager.AIDL_SERVER_REMOTE_GUIDE_ACTIVITY
|
||||
)
|
||||
)
|
||||
requireActivity().startActivity(intent)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,64 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
import android.app.Application
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Environment
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import com.gh.gamecenter.core.runOnIoThread
|
||||
import com.gh.vspace.VHelper
|
||||
import com.lg.vspace.helper.compat.NativeLibraryHelperCompat
|
||||
import com.lightgame.utils.Utils
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
|
||||
class InstallExternalGameViewModel(application: Application) : AndroidViewModel(application) {
|
||||
private val _gamesList = MutableLiveData<List<ExternalGameEntity>>(listOf())
|
||||
val gamesList: LiveData<List<ExternalGameEntity>> = _gamesList
|
||||
private val pkgManger = getApplication<Application>().packageManager
|
||||
private var disposable: Disposable = VHelper.callSite.observeOn(AndroidSchedulers.mainThread()).subscribe {
|
||||
scanPaths()
|
||||
}
|
||||
|
||||
fun scanPaths() {
|
||||
runOnIoThread {
|
||||
_gamesList.postValue(Environment.getExternalStorageDirectory().walk().maxDepth(1)
|
||||
.filter { it.isHidden.not() }
|
||||
.filter { it.isFile }
|
||||
.onEach {
|
||||
Utils.log(Constants.TAG, "获得文件: ${it.name}")
|
||||
}
|
||||
.filter { it.extension == "apk" }
|
||||
.map {
|
||||
val packageInfo = pkgManger.getPackageArchiveInfo(
|
||||
it.absolutePath,
|
||||
PackageManager.GET_META_DATA or PackageManager.GET_ACTIVITIES
|
||||
)
|
||||
packageInfo?.let { packageInfo ->
|
||||
val applicationInfo = packageInfo.applicationInfo
|
||||
applicationInfo.publicSourceDir = it.absolutePath
|
||||
applicationInfo.sourceDir = it.absolutePath
|
||||
ExternalGameEntity(
|
||||
cpuAbi = NativeLibraryHelperCompat.getPackageAbiList(it.absolutePath),
|
||||
apkPath = it.absolutePath,
|
||||
apkFileName = it.name,
|
||||
apkPackageName = packageInfo.packageName,
|
||||
apkVersion = packageInfo.versionName,
|
||||
appName = pkgManger.getApplicationLabel(applicationInfo).toString(),
|
||||
lastModified = it.lastModified()
|
||||
)
|
||||
}
|
||||
}.filterNotNull()
|
||||
.toList().sortedByDescending { it.lastModified }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
disposable.dispose()
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
package com.gh.vspace.installexternalgames
|
||||
|
||||
interface OnItemClickListener {
|
||||
|
||||
enum class ClickType {
|
||||
CLICK_INSTALL, CLICK_UNINSTALL, CLICK_START
|
||||
}
|
||||
|
||||
fun onItemClick(externalGameUiState: ExternalGameUiState, clickType: ClickType)
|
||||
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/external_games_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/apk_file_info"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="20sp"
|
||||
tools:text="文件名:\n路径:" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_install"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_install"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_update"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_update"
|
||||
android:visibility="visible"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_uninstall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_uninstall"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/text_start"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="title_install_external_game">從SD卡安裝</string>
|
||||
<string name="text_install">安裝</string>
|
||||
<string name="text_update">更新</string>
|
||||
<string name="text_uninstall">卸載</string>
|
||||
<string name="text_start">啟動</string>
|
||||
</resources>
|
||||
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<item name="install_game_from_external" type="id" />
|
||||
</resources>
|
||||
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="title_install_external_game">从SD卡安装</string>
|
||||
<string name="text_install">安装</string>
|
||||
<string name="text_update">更新</string>
|
||||
<string name="text_uninstall">卸载</string>
|
||||
<string name="text_start">启动</string>
|
||||
</resources>
|
||||
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<trust-anchors>
|
||||
<!-- Trust user added CAs while debuggable only -->
|
||||
<certificates src="user" />
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
</base-config>
|
||||
</network-security-config>
|
||||
@ -1,30 +0,0 @@
|
||||
package com.gh.gamecenter
|
||||
|
||||
import android.content.Context
|
||||
import com.kwai.monitor.log.TurboAgent
|
||||
import com.kwai.monitor.log.TurboConfig
|
||||
|
||||
object KuaishouHelper {
|
||||
private val mAppId by lazy { BuildConfig.SDK_APP_ID.ifEmpty { "81537" } }
|
||||
private val mAppName by lazy { BuildConfig.SDK_APP_NAME.ifEmpty { "guanghuanzhushou_1" } }
|
||||
|
||||
@JvmStatic
|
||||
fun init(context: Context, channel: String) {
|
||||
TurboAgent.init(
|
||||
TurboConfig.TurboConfigBuilder.create(context)
|
||||
.setAppId(mAppId)
|
||||
.setAppName(mAppName)
|
||||
.setAppChannel(channel)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun onEvent(type: String) {
|
||||
when (type) {
|
||||
"EVENT_ACTIVE" -> TurboAgent.onAppActive()
|
||||
"active_register" -> TurboAgent.onRegister()
|
||||
"EVENT_NEXTDAY_STAY" -> TurboAgent.onNextDayStay()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,65 +0,0 @@
|
||||
package com.gh.gamecenter.provider
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.text.TextUtils
|
||||
import com.gh.gamecenter.BuildConfig
|
||||
import com.gh.gamecenter.KuaishouHelper
|
||||
import com.gh.gamecenter.core.AppExecutor
|
||||
import com.gh.gamecenter.core.provider.IFlavorProvider
|
||||
import com.gh.gamecenter.core.utils.SPUtils
|
||||
import com.gh.gamecenter.core.utils.TimeUtils
|
||||
import com.gh.gamecenter.core.utils.ToastUtils
|
||||
import com.halo.assistant.HaloApp
|
||||
import com.kwai.monitor.payload.TurboHelper
|
||||
import com.tencent.vasdolly.helper.ChannelReaderUtil
|
||||
|
||||
class FlavorProviderImp : IFlavorProvider {
|
||||
|
||||
override fun init(application: Application, activity: Activity, activateRatio: Int) {
|
||||
KuaishouHelper.init(application, getChannelStr(application))
|
||||
|
||||
if (HaloApp.getInstance().isBrandNewInstall) {
|
||||
logEvent("EVENT_ACTIVE")
|
||||
SPUtils.setLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000)
|
||||
} else {
|
||||
val shouldSendRetentionLogEvent =
|
||||
SPUtils.getBoolean("SHOULD_SEND_RETENTION_EVENT", true)
|
||||
val installTimeNotToday =
|
||||
!TimeUtils.isToday(SPUtils.getLong("TIME_OF_BRAND_NEW_INSTALL", System.currentTimeMillis() / 1000))
|
||||
if (shouldSendRetentionLogEvent && installTimeNotToday) {
|
||||
logEvent("EVENT_NEXTDAY_STAY")
|
||||
SPUtils.setBoolean("SHOULD_SEND_RETENTION_EVENT", false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChannelStr(application: Application): String {
|
||||
var channel = if (BuildConfig.USE_DEFAULT_CHANNEL_SDK) {
|
||||
ChannelReaderUtil.getChannel(application)
|
||||
} else {
|
||||
TurboHelper.getChannel(application)
|
||||
}
|
||||
if (channel == null || TextUtils.isEmpty(channel.trim())) {
|
||||
channel = KUAISHOU_CHANNEL
|
||||
}
|
||||
return channel
|
||||
}
|
||||
|
||||
override fun logEvent(content: String) {
|
||||
KuaishouHelper.onEvent(content)
|
||||
}
|
||||
|
||||
override fun logCoreEvent() {
|
||||
logEvent("EVENT_KEY_PATH_OPTIMIZATION")
|
||||
if (BuildConfig.ACTIVATE_REPORTING_RATIO == 1) {
|
||||
AppExecutor.uiExecutor.executeWithDelay({
|
||||
ToastUtils.toast("关键行为 EVENT_KEY_PATH_OPTIMIZATION")
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val KUAISHOU_CHANNEL = "KS-GHZS-01"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
129
app/src/main/assets/ShareSDK.xml
Normal file
129
app/src/main/assets/ShareSDK.xml
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<DevInfor>
|
||||
<!--
|
||||
说明:
|
||||
|
||||
1、表格中的第一项
|
||||
<ShareSDK
|
||||
AppKey="api20" />
|
||||
是必须的,其中的AppKey是您在ShareSDK上注册的开发者帐号的AppKey
|
||||
|
||||
2、所有集成到您项目的平台都应该为其在表格中填写相对应的开发者信息,以新浪微博为例:
|
||||
<SinaWeibo
|
||||
Id="1"
|
||||
SortId="1"
|
||||
AppKey="568898243"
|
||||
AppSecret="38a4f8204cc784f81f9f0daaf31e02e3"
|
||||
RedirectUrl="http://www.mob.com"
|
||||
Enable="true" />
|
||||
其中的SortId是此平台在分享列表中的位置,由开发者自行定义,可以是任何整型数字,数值越大
|
||||
越靠后AppKey、AppSecret和RedirectUrl是您在新浪微博上注册开发者信息和应用后得到的信息
|
||||
Id是一个保留的识别符,整型,ShareSDK不使用此字段,供您在自己的项目中当作平台的识别符。
|
||||
Enable字段表示此平台是否有效,布尔值,默认为true,如果Enable为false,即便平台的jar包
|
||||
已经添加到应用中,平台实例依然不可获取。
|
||||
|
||||
各个平台注册应用信息的地址如下:
|
||||
新浪微博 http://open.weibo.com
|
||||
腾讯微博 http://dev.t.qq.com
|
||||
QQ空间 http://connect.qq.com/intro/login/
|
||||
微信好友 http://open.weixin.qq.com
|
||||
Facebook https://developers.facebook.com
|
||||
Twitter https://dev.twitter.com
|
||||
人人网 http://dev.renren.com
|
||||
开心网 http://open.kaixin001.com
|
||||
搜狐微博 http://open.t.sohu.com
|
||||
网易微博 http://open.t.163.com
|
||||
豆瓣 http://developers.douban.com
|
||||
|
||||
有道云笔记 http://note.youdao.com/open/developguide.html#app
|
||||
印象笔记 https://dev.evernote.com/
|
||||
Linkedin https://developer.linkedin.com
|
||||
FourSquare https://developer.foursquare.com/
|
||||
搜狐随身看 https://open.sohu.com/
|
||||
Flickr http://www.flickr.com/services/
|
||||
Pinterest http://developers.pinterest.com/
|
||||
Tumblr http://www.tumblr.com/developers
|
||||
Dropbox https://www.dropbox.com/developers
|
||||
Instagram http://instagram.com/developer#
|
||||
VKontakte http://vk.com/dev
|
||||
易信好友 http://open.yixin.im/
|
||||
明道 http://open.mingdao.com/
|
||||
Line http://media.line.me/zh-hant/
|
||||
Pocket http://getpocket.com/developer/apps/new
|
||||
-->
|
||||
|
||||
<ShareSDK
|
||||
AppKey = "6f286c8a261a"/> <!-- 修改成你在sharesdk后台注册的应用的appkey"-->
|
||||
|
||||
<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
|
||||
<SinaWeibo
|
||||
Id="1"
|
||||
SortId="1"
|
||||
AppKey="568898243"
|
||||
AppSecret="38a4f8204cc784f81f9f0daaf31e02e3"
|
||||
RedirectUrl="http://www.sharesdk.cn"
|
||||
ShareByAppClient="false"
|
||||
Enable="true" />
|
||||
|
||||
<TencentWeibo
|
||||
Id="2"
|
||||
SortId="2"
|
||||
AppKey="801307650"
|
||||
AppSecret="ae36f4ee3946e1cbb98d6965b0b2ff5c"
|
||||
RedirectUri="http://sharesdk.cn"
|
||||
Enable="true" />
|
||||
|
||||
<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
|
||||
<QZone
|
||||
Id="3"
|
||||
SortId="3"
|
||||
AppId="1104659243"
|
||||
AppKey="OfjHS7bWyxPiH0t8"
|
||||
ShareByAppClient="true"
|
||||
Enable="true" />
|
||||
|
||||
<!--
|
||||
Wechat微信和WechatMoments微信朋友圈的appid是一样的;
|
||||
|
||||
注意:开发者不能用我们这两个平台的appid,否则分享不了
|
||||
|
||||
微信测试的时候,微信测试需要先签名打包出apk,
|
||||
sample测试微信,要先签名打包,keystore在sample项目中,密码123456
|
||||
|
||||
BypassApproval是绕过审核的标记,设置为true后AppId将被忽略,故不经过
|
||||
审核的应用也可以执行分享,但是仅限于分享文字和图片,不能分享其他类型,
|
||||
默认值为false。此外,微信收藏不支持此字段。
|
||||
-->
|
||||
<Wechat
|
||||
Id="4"
|
||||
SortId="4"
|
||||
AppId="wx4868b35061f87885"
|
||||
AppSecret="64020361b8ec4c99936c0e3999a9f249"
|
||||
BypassApproval="true"
|
||||
Enable="true" />
|
||||
|
||||
<WechatMoments
|
||||
Id="5"
|
||||
SortId="5"
|
||||
AppId="wx4868b35061f87885"
|
||||
AppSecret="64020361b8ec4c99936c0e3999a9f249"
|
||||
BypassApproval="true"
|
||||
Enable="true" />
|
||||
|
||||
<WechatFavorite
|
||||
Id="6"
|
||||
SortId="6"
|
||||
AppId="wx4868b35061f87885"
|
||||
AppSecret="64020361b8ec4c99936c0e3999a9f249"
|
||||
Enable="true" />
|
||||
|
||||
<!-- ShareByAppClient标识是否使用微博客户端分享,默认是false -->
|
||||
<QQ
|
||||
Id="7"
|
||||
SortId="7"
|
||||
AppId="1104659243"
|
||||
AppKey="OfjHS7bWyxPiH0t8"
|
||||
ShareByAppClient="true"
|
||||
Enable="true" />
|
||||
|
||||
</DevInfor>
|
||||
@ -1,163 +0,0 @@
|
||||
function requestContentFocus() {
|
||||
$("#editor").focus();
|
||||
}
|
||||
|
||||
function setupWhenContentEditable() {
|
||||
var editor = $("#editor");
|
||||
if (!editor[0].hasAttribute("contenteditable")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// paste
|
||||
editor.on("paste", function(e) {
|
||||
e.preventDefault();
|
||||
var text = (e.originalEvent || e).clipboardData.getData("text/plain");
|
||||
text = text.replace(/\n/g, "<br>");
|
||||
if ("" != text) {
|
||||
document.execCommand("insertHTML", false, text);
|
||||
} else {
|
||||
window.onPasteListener.onPaste();
|
||||
}
|
||||
});
|
||||
|
||||
requestContentFocus();
|
||||
}
|
||||
|
||||
function getStyle(dom, name) {
|
||||
return window.getComputedStyle(dom)[name];
|
||||
}
|
||||
|
||||
function customLinkgo(self) {
|
||||
var datas = self.dataset.datas;
|
||||
console.log(datas)
|
||||
window.OnLinkClickListener.onClick(datas);
|
||||
}
|
||||
|
||||
var typeClassList = [
|
||||
"community_article-container",
|
||||
"answer-container",
|
||||
"game-container"
|
||||
];
|
||||
|
||||
function removeDomByParent(curDom) {
|
||||
if (curDom.parentElement) {
|
||||
curDom.parentElement.removeChild(curDom);
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("load", function() {
|
||||
var EditorDom = document.querySelector("#editor");
|
||||
setupWhenContentEditable();
|
||||
|
||||
document.addEventListener("keydown", function(e) {
|
||||
var event = e || window.event;
|
||||
|
||||
if (event.keyCode === 8) {
|
||||
var s = document.getSelection();
|
||||
var r = s.getRangeAt(0);
|
||||
|
||||
if (r.startOffset === r.endOffset && r.endOffset === 0) {
|
||||
var preDOM = s.focusNode.previousElementSibling;
|
||||
|
||||
if (
|
||||
preDOM &&
|
||||
preDOM instanceof Element &&
|
||||
preDOM.nodeName === "IMG" &&
|
||||
getStyle(preDOM, "display") === "block"
|
||||
) {
|
||||
preDOM.parentElement.removeChild(preDOM);
|
||||
}
|
||||
}
|
||||
|
||||
var customDom = s.focusNode;
|
||||
if (customDom) {
|
||||
if (
|
||||
r.startContainer.nodeName.toLowerCase() === "blockquote" &&
|
||||
r.startOffset === 0
|
||||
) {
|
||||
RE.formatBlock();
|
||||
e.preventDefault();
|
||||
} else if (
|
||||
customDom.nodeName === "#text" &&
|
||||
customDom.previousElementSibling &&
|
||||
typeClassList.indexOf(customDom.previousElementSibling.className) >
|
||||
-1 &&
|
||||
r.startOffset === 1
|
||||
) {
|
||||
var needDeleteDom = customDom.previousElementSibling;
|
||||
needDeleteDom.insertAdjacentElement(
|
||||
"afterend",
|
||||
document.createElement("br")
|
||||
);
|
||||
} else if (
|
||||
customDom instanceof Element &&
|
||||
customDom.childNodes[s.focusOffset] &&
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling &&
|
||||
typeClassList.indexOf(
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling.className
|
||||
) > -1
|
||||
) {
|
||||
customDom =
|
||||
customDom.childNodes[s.focusOffset].previousElementSibling;
|
||||
customDom.parentElement.removeChild(customDom);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("keyup", function(e) {
|
||||
var event = e || window.event;
|
||||
if (event.keyCode === 13) {
|
||||
var s = document.getSelection();
|
||||
var curDom = s.focusNode;
|
||||
var preDom = curDom.previousElementSibling;
|
||||
|
||||
if (
|
||||
curDom.nodeName.toLowerCase() === "blockquote" &&
|
||||
preDom.nodeName.toLowerCase() === "blockquote"
|
||||
) {
|
||||
if (
|
||||
preDom.childNodes.length > 1 ||
|
||||
(preDom.childNodes.length === 1 &&
|
||||
preDom.childNodes[0].tagName !== "BR")
|
||||
) {
|
||||
curDom.style.marginTop = 0;
|
||||
preDom.style.marginBottom = 0;
|
||||
} else if (
|
||||
(curDom.childNodes.length === 0 ||
|
||||
(curDom.childNodes.length === 1 &&
|
||||
curDom.childNodes[0].tagName === "BR")) &&
|
||||
(preDom.childNodes.length === 0 ||
|
||||
(preDom.childNodes.length === 1 &&
|
||||
preDom.childNodes[0].tagName === "BR"))
|
||||
) {
|
||||
|
||||
removeDomByParent(curDom);
|
||||
|
||||
var startQuoteDom = preDom.previousElementSibling;
|
||||
startQuoteDom && startQuoteDom.nodeName.toLowerCase() === "blockquote"
|
||||
? (startQuoteDom.style.marginBottom = "10px")
|
||||
: null;
|
||||
|
||||
var range = document.createRange();
|
||||
range.selectNode(preDom);
|
||||
s.removeAllRanges();
|
||||
s.addRange(range);
|
||||
|
||||
RE.formatBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
var event = e || window.event;
|
||||
var targetDom = event.target.activeElement;
|
||||
if (targetDom.id === "editor" && targetDom.lastElementChild) {
|
||||
if (typeClassList.indexOf(targetDom.lastElementChild.className) > -1) {
|
||||
var brDom = document.createElement("br");
|
||||
EditorDom.appendChild(brDom);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1,27 +0,0 @@
|
||||
{
|
||||
"easyGoVersion": "1.0",
|
||||
"client": "com.gh.gamecenter",
|
||||
"logicEntities": [
|
||||
{
|
||||
"head": {
|
||||
"function": "magicwindow",
|
||||
"required": "true"
|
||||
},
|
||||
"body": {
|
||||
"mode":"1",
|
||||
"activityPairs":[
|
||||
{"from":"com.gh.gamecenter.MainActivity","to":"*"}
|
||||
],
|
||||
"defaultDualActivities": {
|
||||
"mainPages": "com.gh.gamecenter.MainActivity"
|
||||
},
|
||||
"UX": {
|
||||
"supportRotationUxCompat": "false",
|
||||
"isDraggable": "true"
|
||||
},
|
||||
"transActivities":[
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<link rel="stylesheet" type="text/css" href="normalize.css">
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="video-js.min.css">
|
||||
</head>
|
||||
|
||||
<body style="overflow-x: hidden; word-break: break-all;">
|
||||
<div id="editor" contenteditable="false"></div>
|
||||
<script type="text/javascript" src="zepto.min.js"></script>
|
||||
<script type="text/javascript" src="rich_editor.js"></script>
|
||||
<script type="text/javascript" src="video.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
BIN
app/src/main/assets/hackdex_dex.jar
Normal file
BIN
app/src/main/assets/hackdex_dex.jar
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":100,"w":64,"h":64,"nm":"多版本下载提示_dark","ddd":0,"assets":[{"id":"comp_0","nm":"arrow 合成_dark","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"arrow","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.333],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.667],"y":[0]},"t":76,"s":[100]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.333,"y":1},"o":{"x":0.364,"y":0},"t":0,"s":[28,-12,0],"to":[0,6.382,0],"ti":[0,-0.284,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":24,"s":[28,28,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.667,"y":0},"t":76,"s":[28,28,0],"to":[0,6.667,0],"ti":[0,-6.667,0]},{"t":100,"s":[28,68,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,2],[0,-2]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2,0],[0,2]],"c":false},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2,0],[0,2]],"c":false},"ix":2},"nm":"路径 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.333,0.333],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[80,120]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.667,0.667],"y":[0,0]},"t":24,"s":[100,100]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.667,0.667],"y":[0,0]},"t":76,"s":[100,100]},{"t":100,"s":[80,120]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.156862750649,0.533333361149,0.878431379795,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[400,400],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Vector 97","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":100,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow 合成_dark","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2,"l":2},"a":{"a":0,"k":[28,28,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":56,"h":56,"ip":0,"op":100,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"base","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[15,15],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.156862750649,0.533333361149,0.878431379795,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.137254908681,0.137254908681,0.137254908681,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"filling","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[400,400],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Ellipse 44","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":100,"st":0,"bm":0}],"markers":[]}
|
||||
@ -1 +0,0 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":100,"w":64,"h":64,"nm":"多版本下载提示_light","ddd":0,"assets":[{"id":"comp_0","nm":"arrow 合成_light","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"arrow","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.333],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.667],"y":[0]},"t":76,"s":[100]},{"t":100,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.333,"y":1},"o":{"x":0.364,"y":0},"t":0,"s":[28,-12,0],"to":[0,6.382,0],"ti":[0,-0.284,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":24,"s":[28,28,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.667,"y":0},"t":76,"s":[28,28,0],"to":[0,6.667,0],"ti":[0,-6.667,0]},{"t":100,"s":[28,68,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,2],[0,-2]],"c":false},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-2,0],[0,2]],"c":false},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2,0],[0,2]],"c":false},"ix":2},"nm":"路径 3","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.333,0.333],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":0,"s":[80,120]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.667,0.667],"y":[0,0]},"t":24,"s":[100,100]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.667,0.667],"y":[0,0]},"t":76,"s":[100,100]},{"t":100,"s":[80,120]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.141176477075,0.588235318661,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[400,400],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Vector 97","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":100,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow 合成_light","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2,"l":2},"a":{"a":0,"k":[28,28,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":56,"h":56,"ip":0,"op":100,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"base","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[32,32,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[15,15],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.141176477075,0.588235318661,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"stroke","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"filling","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[400,400],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Ellipse 44","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":100,"st":0,"bm":0}],"markers":[]}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":144,"h":144,"nm":"icon_change","ddd":0,"assets":[{"id":"comp_0","nm":"icon_change_detail","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"stroke1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[37.04,52.994,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.533,-0.143],[0.143,-0.533],[1.487,-1.304],[1.961,-0.258],[1.774,0.875],[0.709,0.661],[0,0],[0,0.445],[0,0],[-0.276,0],[0,0],[-0.013,0],[0,0],[0.315,-0.315],[0,0],[-0.682,-0.336],[-1.569,0.207],[-1.19,1.043],[-0.41,1.528]],"o":[[0.533,0.143],[-0.512,1.91],[-1.487,1.304],[-1.961,0.258],[-0.879,-0.433],[0,0],[-0.315,0.315],[0,0],[0,-0.276],[0,0],[0.013,0],[0,0],[0.445,0],[0,0],[0.555,0.508],[1.419,0.7],[1.569,-0.207],[1.19,-1.043],[0.143,-0.533]],"v":[[8.605,-4.301],[9.312,-3.076],[6.247,1.854],[0.958,4.25],[-4.77,3.304],[-7.163,1.652],[-8.493,2.982],[-9.347,2.628],[-9.347,-1.665],[-8.847,-2.165],[-8.161,-2.165],[-8.122,-2.165],[-4.554,-2.165],[-4.2,-1.311],[-5.748,0.237],[-3.885,1.51],[0.697,2.267],[4.928,0.35],[7.381,-3.594]],"c":true},"ix":2},"nm":"stroke1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[-5.347,-4.665],"ix":5},"e":{"a":0,"k":[8.653,-4.665],"ix":6},"t":1,"nm":"color1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"stroke1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"stroke2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.96,19.006,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.961,0.258],[-1.774,-0.875],[-0.709,-0.661],[0,0],[0,-0.445],[0,0],[0.276,0],[0,0],[0.012,0],[0,0],[-0.315,0.315],[0,0],[0.682,0.336],[1.569,-0.207],[1.19,-1.043],[0.41,-1.528],[0.533,0.143],[-0.143,0.533],[-1.487,1.304]],"o":[[1.961,-0.258],[0.879,0.433],[0,0],[0.315,-0.315],[0,0],[0,0.276],[0,0],[-0.012,0],[0,0],[-0.445,0],[0,0],[-0.555,-0.508],[-1.419,-0.7],[-1.569,0.207],[-1.19,1.043],[-0.143,0.533],[-0.533,-0.143],[0.512,-1.91],[1.487,-1.304]],"v":[[-0.958,-4.25],[4.77,-3.304],[7.163,-1.652],[8.493,-2.982],[9.347,-2.628],[9.347,1.665],[8.847,2.165],[8.16,2.165],[8.123,2.165],[4.554,2.165],[4.2,1.311],[5.748,-0.237],[3.885,-1.51],[-0.697,-2.267],[-4.928,-0.35],[-7.381,3.594],[-8.605,4.301],[-9.312,3.076],[-6.247,-1.854]],"c":true},"ix":2},"nm":"stroke2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,1,1,1,0.5,1,1,1,1,1,1,1,0,1,0.5,0.8,1,0.6],"ix":9}},"s":{"a":0,"k":[5.347,4.665],"ix":5},"e":{"a":0,"k":[-8.653,4.665],"ix":6},"t":1,"nm":"color2","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"stroke2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon_change_detail","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[36,36,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":72,"h":72,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
|
||||
@ -1 +0,0 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":72,"h":72,"nm":"icon_title_change","ddd":0,"assets":[{"id":"comp_0","nm":"arrow","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"arrow_e_dark","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[29.25,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.701,0.456],[-1.627,-0.674],[-0.705,-0.667],[0,0],[-0.552,0],[0,-0.552],[0,0],[0.552,0],[0,0],[0.012,0],[0,0],[0,0.552],[-0.552,0],[0,0],[0.615,0.255],[1.276,-0.342],[0.804,-1.048],[0,-1.321],[-0.804,-1.048],[-1.276,-0.342],[-1.22,0.505],[-0.66,1.144],[-0.478,-0.276],[0.276,-0.478],[1.627,-0.674],[1.701,0.456],[1.072,1.397],[0,1.761],[-1.072,1.397]],"o":[[1.701,-0.456],[0.909,0.376],[0,0],[0,-0.552],[0.552,0],[0,0],[0,0.552],[0,0],[-0.012,0],[0,0],[-0.552,0],[0,-0.552],[0,0],[-0.493,-0.435],[-1.22,-0.505],[-1.276,0.342],[-0.804,1.048],[0,1.321],[0.804,1.048],[1.276,0.342],[1.22,-0.505],[0.276,-0.478],[0.478,0.276],[-0.881,1.525],[-1.627,0.674],[-1.701,-0.456],[-1.072,-1.397],[0,-1.761],[1.072,-1.397]],"v":[[-1.821,-7.727],[3.311,-7.391],[5.75,-5.809],[5.75,-6.5],[6.75,-7.5],[7.75,-6.5],[7.75,-3.5],[6.75,-2.5],[6.331,-2.5],[6.295,-2.5],[3.75,-2.5],[2.75,-3.5],[3.75,-4.5],[4.219,-4.5],[2.546,-5.543],[-1.303,-5.796],[-4.51,-3.653],[-5.75,0],[-4.51,3.653],[-1.303,5.796],[2.546,5.543],[5.446,3],[6.812,2.634],[7.178,4],[3.311,7.391],[-1.821,7.727],[-6.097,4.87],[-7.75,0],[-6.097,-4.87]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.158117651939,0.532358944416,0.878431379795,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"arrow_e_dark","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":60,"h":60,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
|
||||
@ -1 +0,0 @@
|
||||
{"v":"5.9.1","fr":60,"ip":0,"op":60,"w":72,"h":72,"nm":"icon_title_change","ddd":0,"assets":[{"id":"comp_0","nm":"arrow","fr":60,"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"arrow_e_light","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[29.25,30,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.701,0.456],[-1.627,-0.674],[-0.705,-0.667],[0,0],[-0.552,0],[0,-0.552],[0,0],[0.552,0],[0,0],[0.012,0],[0,0],[0,0.552],[-0.552,0],[0,0],[0.615,0.255],[1.276,-0.342],[0.804,-1.048],[0,-1.321],[-0.804,-1.048],[-1.276,-0.342],[-1.22,0.505],[-0.66,1.144],[-0.478,-0.276],[0.276,-0.478],[1.627,-0.674],[1.701,0.456],[1.072,1.397],[0,1.761],[-1.072,1.397]],"o":[[1.701,-0.456],[0.909,0.376],[0,0],[0,-0.552],[0.552,0],[0,0],[0,0.552],[0,0],[-0.012,0],[0,0],[-0.552,0],[0,-0.552],[0,0],[-0.493,-0.435],[-1.22,-0.505],[-1.276,0.342],[-0.804,1.048],[0,1.321],[0.804,1.048],[1.276,0.342],[1.22,-0.505],[0.276,-0.478],[0.478,0.276],[-0.881,1.525],[-1.627,0.674],[-1.701,-0.456],[-1.072,-1.397],[0,-1.761],[1.072,-1.397]],"v":[[-1.821,-7.727],[3.311,-7.391],[5.75,-5.809],[5.75,-6.5],[6.75,-7.5],[7.75,-6.5],[7.75,-3.5],[6.75,-2.5],[6.331,-2.5],[6.295,-2.5],[3.75,-2.5],[2.75,-3.5],[3.75,-4.5],[4.219,-4.5],[2.546,-5.543],[-1.303,-5.796],[-4.51,-3.653],[-5.75,0],[-4.51,3.653],[-1.303,5.796],[2.546,5.543],[5.446,3],[6.812,2.634],[7.178,4],[3.311,7.391],[-1.821,7.727],[-6.097,4.87],[-7.75,0],[-6.097,-4.87]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.141176477075,0.588235318661,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"填充 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"arrow_e_light","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"arrow","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":0,"s":[0]},{"t":36,"s":[360]}],"ix":10},"p":{"a":0,"k":[36,36,0],"ix":2,"l":2},"a":{"a":0,"k":[30,30,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":60,"h":60,"ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
{"v":"5.5.9","fr":30,"ip":0,"op":20,"w":66,"h":66,"nm":"tab_index","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"椭圆形备份","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.596],"y":[0]},"t":0,"s":[0]},{"t":6,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,40.493,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.54,0.54,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.555,0.555,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.552,0.552,0.333],"y":[0,0,0]},"t":13,"s":[90,90,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[5,5],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"椭圆路径 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.635],"y":[0]},"t":0,"s":[0]},{"t":8,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"修剪路径 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.5,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形备份","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-0.5,"op":59.5,"st":-0.5,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"路径备份","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,32.993,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.508,0.508,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.488,0.488,0.333],"y":[0,0,0]},"t":4,"s":[80,80,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.502,0.502,0.333],"y":[0,0,0]},"t":9,"s":[110,110,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.534,0.534,0.333],"y":[0,0,0]},"t":13,"s":[95,95,100]},{"t":16,"s":[100,100,100]}],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.24,-1.21],[-1.93,-1.89],[-0.24,-0.57],[0,-0.06],[0,-2.63],[1.76,0],[0,0],[0,1.72],[0,2.63],[-0.24,0.61],[-0.03,0.02],[-1.93,1.89]],"o":[[1.92,1.89],[0.02,0.02],[0.24,0.57],[0,2.63],[0,1.72],[0,0],[-1.76,0],[0,-2.62],[0,-0.07],[0.25,-0.61],[1.92,-1.89],[1.24,-1.21]],"v":[[2.26,-9.09],[8.03,-3.42],[8.76,-2.38],[9,-1.02],[9,6.88],[5.82,10],[-5.82,10],[-9,6.88],[-9,-0.99],[-8.71,-2.38],[-8.01,-3.43],[-2.23,-9.09]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.266,0.638,1,0.5,0.242,0.595,1,1,0.217,0.552,1],"ix":9}},"s":{"a":0,"k":[-4.902,-4.663],"ix":5},"e":{"a":0,"k":[8.159,8.646],"ix":6},"t":1,"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"路径备份","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"bm":0}],"markers":[]}
|
||||
@ -1 +0,0 @@
|
||||
{"v":"5.12.2","fr":60,"ip":0,"op":40,"w":66,"h":66,"nm":"icon_tab_my","ddd":0,"assets":[{"id":"comp_0","nm":"icon","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"highlight","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33.134,34.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":0.733},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,-0.004],[0.493,0],[0,0.004],[-0.493,0]],"o":[[0,0.004],[-0.493,0],[0,-0.004],[0.493,0]],"v":[[0.893,1.488],[0,1.496],[-0.893,1.488],[0,1.483]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.267},"t":10,"s":[{"i":[[0,-1.018],[1.793,0],[0,1.018],[-1.793,0]],"o":[[0,1.018],[-1.793,0],[0,-1.018],[1.793,0]],"v":[[2.914,-0.344],[0,1.5],[-2.914,-0.344],[0,-1.5]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":18,"s":[{"i":[[0,-1.181],[1.407,0],[0,1.181],[-1.407,0]],"o":[[0,1.181],[-1.407,0],[0,-1.181],[1.407,0]],"v":[[2.226,-0.341],[0,1.74],[-2.211,-0.341],[0,-1.74]],"c":true}]},{"i":{"x":0.333,"y":1},"o":{"x":0.667,"y":0},"t":26,"s":[{"i":[[0,-0.905],[1.381,0],[0,0.905],[-1.381,0]],"o":[[0,0.905],[-1.381,0],[0,-0.905],[1.381,0]],"v":[[2.5,-0.306],[0,1.333],[-2.5,-0.306],[0,-1.333]],"c":true}]},{"t":32,"s":[{"i":[[0,-1.018],[1.381,0],[0,1.018],[-1.381,0]],"o":[[0,1.018],[-1.381,0],[0,-1.018],[1.381,0]],"v":[[2.5,-0.344],[0,1.5],[-2.5,-0.344],[0,-1.5]],"c":true}]}],"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"color","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"椭圆形","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"body","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,34.204,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-3.866,0],[0,3.866],[3.866,0],[0,-3.866]],"o":[[3.866,0],[0,-3.866],[-3.866,0],[0,3.866]],"v":[[0,4.599],[7,-2.401],[0,-9.401],[-7,-2.401]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0.207,0.359],[2.438,0],[1.189,-2.104],[-0.361,-0.204],[-0.204,0.361],[-1.915,0],[-0.932,-1.613],[-0.359,0.207]],"o":[[-1.198,-2.072],[-2.462,0],[-0.204,0.361],[0.361,0.204],[0.925,-1.638],[1.897,0],[0.207,0.359],[0.359,-0.207]],"v":[[5.848,8.225],[0,4.849],[-5.88,8.282],[-5.596,9.304],[-4.574,9.02],[0,6.349],[4.549,8.976],[5.574,9.25]],"c":true},"ix":2},"nm":"路径 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"合并路径 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":3,"k":{"a":0,"k":[0,0.267,0.639,1,0.5,0.241,0.596,1,1,0.216,0.553,1],"ix":9}},"s":{"a":0,"k":[-3.812,-4.384],"ix":5},"e":{"a":0,"k":[6.345,8.129],"ix":6},"t":1,"nm":"color","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[300,300],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"Union","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":60,"st":0,"ct":1,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"icon","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[33,33,0],"ix":2,"l":2},"a":{"a":0,"k":[33,33,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[100,100,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":8,"s":[70,70,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":18,"s":[110,110,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":26,"s":[90,90,100]},{"t":32,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"w":66,"h":66,"ip":0,"op":60,"st":0,"bm":0}],"markers":[],"props":{}}
|
||||
File diff suppressed because one or more lines are too long
413
app/src/main/assets/normalize.css
vendored
413
app/src/main/assets/normalize.css
vendored
@ -1,413 +0,0 @@
|
||||
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS text size adjust after orientation change, without disabling
|
||||
* user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability when focused and also mouse hovered in all browsers.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
-webkit-box-sizing: content-box; /* 2 */
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
||||
15011
app/src/main/assets/package.txt
Normal file
15011
app/src/main/assets/package.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,149 +1,30 @@
|
||||
9u=\u4e5d\u6e38
|
||||
4399=\u0034\u0033\u0039\u0039
|
||||
yyb=\u5e94\u7528\u5b9d
|
||||
xm=\u5c0f\u7c73
|
||||
dl=\u5f53\u4e50
|
||||
91=\u0039\u0031
|
||||
yw=\u76ca\u73a9
|
||||
gf-w=\u5b98\u65b9\u5916
|
||||
az=\u5b89\u667a
|
||||
oppo=\u006f\u0070\u0070\u006f
|
||||
wdj=\u8c4c\u8c46\u835a
|
||||
360=\u0033\u0036\u0030
|
||||
vivo=\u0076\u0069\u0076\u006f
|
||||
pps=\u0050\u0050\u0053
|
||||
hw=\u534e\u4e3a
|
||||
37=\u0033\u0037\u73a9
|
||||
baidu=\u767e\u5ea6
|
||||
ow=\u5076\u73a9
|
||||
gf=\u5b98\u65b9
|
||||
lenovo=\u8054\u60f3
|
||||
pptv=\u0050\u0050\u0054\u0056
|
||||
jf=\u673a\u950b
|
||||
mumayi=\u6728\u8682\u8681
|
||||
8868=\u0038\u0038\u0036\u0038
|
||||
19196=\u0031\u0039\u0031\u0039\u0036
|
||||
07073=\u0030\u0037\u0030\u0037\u0033
|
||||
gp=\u679c\u76d8
|
||||
mzw=\u62c7\u6307\u73a9
|
||||
af=\u5b89\u950b
|
||||
lb=\u730e\u5b9d
|
||||
ayx=\u963f\u6e38\u620f
|
||||
tt=\u0054\u0054
|
||||
xiongmao=\u718a\u732b\u73a9
|
||||
aq=\u5b89\u8da3
|
||||
ls=\u4e50\u89c6
|
||||
jl=\u91d1\u7acb
|
||||
lehh=\u4e50\u55e8\u55e8
|
||||
pyw=\u670b\u53cb\u73a9
|
||||
azsc=\u5b89\u5353\u5e02\u573a
|
||||
hyx=\u548c\u6e38\u620f
|
||||
aiyouxi=\u7231\u6e38\u620f
|
||||
woyouxi=\u6c83\u6e38\u620f
|
||||
lg=\u4e50\u8d2d\u0028\u70b9\u70b9\u0029
|
||||
gf-h=\u0028\u65e7\u0029\u5b98\u65b9\u4e13\u670d
|
||||
gf-z=\u0028\u65e7\u0029\u5b98\u65b9\u6df7\u670d
|
||||
gfzf=\u5b98\u65b9\u4e13\u670d
|
||||
gfhf=\u5b98\u65b9\u6df7\u670d
|
||||
owzf=\u5076\u73a9\u4e13\u670d
|
||||
gf-n=\u5b98\u65b9\u5185
|
||||
my=\u9b54\u9047
|
||||
jinshan=\u91d1\u5c71
|
||||
duoku=\u591a\u9177
|
||||
yk=\u4f18\u9177
|
||||
xl=\u65b0\u6d6a
|
||||
sougou=\u641c\u72d7
|
||||
dy=\u6597\u9c7c
|
||||
dw=\u591a\u73a9
|
||||
tf=\u53f0\u670d
|
||||
xunlei=\u8fc5\u96f7
|
||||
ky=\u5feb\u7528
|
||||
lenvono=\u0028\u65e7\u0029\u8054\u60f3
|
||||
jifeng=\u0028\u65e7\u0029\u673a\u950b
|
||||
anzhi=\u0028\u65e7\u0029\u5b89\u667a
|
||||
37wan=\u0028\u65e7\u0029\u0033\u0037\u73a9
|
||||
ewan=\u0028\u65e7\u0029\u76ca\u73a9
|
||||
mi=\u0028\u65e7\u0029\u5c0f\u7c73
|
||||
dangle=\u0028\u65e7\u0029\u5f53\u4e50
|
||||
ouwan=\u0028\u65e7\u0029\u5076\u73a9
|
||||
ttyy=\u0028\u65e7\u0029\u0054\u0054
|
||||
huawei=\u0028\u65e7\u0029\u534e\u4e3a
|
||||
shuizhu=\u0028\u65e7\u0029\u6c34\u716e
|
||||
43997=\u0034\u0033\u0039\u0039\u0037
|
||||
19196zf=\u0031\u0039\u0031\u0039\u0036\u4e13\u670d
|
||||
51508=\u0035\u0031\u0035\u0030\u0038
|
||||
zzb=\u81f3\u5c0a\u5b9d
|
||||
wkd=\u73a9\u5ba2\u7248
|
||||
yq=\u4f18\u8da3
|
||||
tiantian=\u5929\u5929
|
||||
ddw=\u70b9\u70b9\u73a9
|
||||
by=\u7206\u6e38
|
||||
as=\u7231\u4e0a
|
||||
flb=\u5c0f\u7b28\u6e38\u620f
|
||||
cf=\u695a\u98ce
|
||||
itools=\u0049\u0054\u004f\u004f\u004c\u0053
|
||||
ayw=\u7231\u7ea6\u73a9
|
||||
cc=\u866b\u866b
|
||||
kpzs=\u9760\u8c31\u52a9\u624b
|
||||
xtt=\u65b0\u0074\u0074
|
||||
yt=\u6e38\u9014\u7248
|
||||
9665=\u0039\u0036\u0036\u0035
|
||||
lehhkf=\u4e50\u55e8\u55e8\u006b\u0066
|
||||
lehhol=\u4e50\u55e8\u55e8\u006f\u006c
|
||||
afly=\u5b89\u950b\u006c\u0079
|
||||
360hf=\u0033\u0036\u0030\u6df7\u670d\u7248
|
||||
qql=\u9f50\u9f50\u4e50
|
||||
yehuo=\u91ce\u706b\u7248
|
||||
jizhi=\u6781\u81f4\u7248
|
||||
shengxun=\u76db\u8baf\u6e38\u620f
|
||||
9upt=\u4e5d\u6e38\u666e\u901a\u7248
|
||||
9ujs=\u4e5d\u6e38\u52a0\u901f\u7248
|
||||
xmpt=\u5c0f\u7c73\u666e\u901a\u7248
|
||||
xmjs=\u5c0f\u7c73\u52a0\u901f\u7248
|
||||
gfpt=\u5b98\u65b9\u666e\u901a\u7248
|
||||
gfjs=\u5b98\u65b9\u52a0\u901f\u7248
|
||||
wkd1=\u73a9\u5ba2\u65b0\u7248
|
||||
5288=\u0035\u0032\u0038\u0038
|
||||
7guo=\u4e03\u679c
|
||||
zhanyou=\u5c55\u6e38\u7248
|
||||
babie=\u5df4\u522b\u65f6\u4ee3\u7248
|
||||
yueyou=\u7ea6\u6e38\u7248
|
||||
kuniu=\u9177\u725b\u7248
|
||||
chukong=\u89e6\u63a7\u7248
|
||||
changxiang=\u7545\u60f3\u7248
|
||||
zhuohua=\u707c\u534e\u7248
|
||||
duokemeng=\u54c6\u53ef\u68a6\u7248
|
||||
xuanyun=\u7384\u4e91\u7248
|
||||
hanqu=\u701a\u8da3\u7248
|
||||
wapu=\u86d9\u6251\u7248
|
||||
shengli=\u80dc\u5229\u6e38\u620f\u7248
|
||||
heitao=\u9ed1\u6843\u4e92\u52a8\u7248
|
||||
xumei=\u65ed\u6885\u6e38\u620f\u7248
|
||||
weixun=\u5fae\u8baf\u7248
|
||||
tianxiang=\u5929\u8c61\u4e92\u52a8\u7248
|
||||
taiqi=\u6cf0\u5947\u7248
|
||||
chujian=\u521d\u89c1\u7248
|
||||
gaiya=\u76d6\u5a05\u7248
|
||||
wanmei=\u5b8c\u7f8e\u4e16\u754c\u7248
|
||||
zhuoyue=\u5353\u8d8a\u7248
|
||||
meifeng=\u7f8e\u5cf0\u7248
|
||||
xuanji=\u7384\u673a\u7248
|
||||
changyou=\u7545\u6e38\u7248
|
||||
syg=\u624b\u6e38\u72d7
|
||||
youzu=\u6e38\u65cf\u7248
|
||||
bili=\u0062\u0069\u006c\u0069\u0062\u0069\u006c\u0069\u7248
|
||||
ly=\u4e50\u6e38
|
||||
gfwy=\u7f51\u9875\u7248
|
||||
miqi=\u7c73\u5947\u73a9
|
||||
ayw=\u6e38\u620f\u0066\u0061\u006e
|
||||
ys=\u591c\u795e\u7248
|
||||
aofei=\u5965\u98de
|
||||
mgw=\u8611\u83c7\u73a9
|
||||
longc=\u9f99\u57ce\u7248
|
||||
16y=\u0031\u0036\u6e38
|
||||
xq=\u5c0f\u4e03
|
||||
yuwan=\u9c7c\u4e38\u7248
|
||||
jgp=\u679c\u76d8\u65e7
|
||||
lequ=\u6dd8\u8da3
|
||||
jianguo=\u575a\u679c\u7248
|
||||
yanmeng=\u5ef6\u68a6\u7248
|
||||
9u=\u4E5D\u6E38\u7248
|
||||
360=360\u7248
|
||||
baidu=\u767E\u5EA6\u7248
|
||||
dangle=\u5F53\u4E50\u7248
|
||||
ouwan=\u5076\u73A9\u7248
|
||||
gf=\u5B98\u65B9\u7248
|
||||
mi=\u5C0F\u7C73\u7248
|
||||
oppo=OPPO\u7248
|
||||
91=91\u7248
|
||||
wdj=\u8C4C\u8C46\u835A\u7248
|
||||
vivo=VIVO\u7248
|
||||
pps=PPS\u7248
|
||||
37wan=37\u73A9\u7248
|
||||
anzhi=\u5B89\u667A\u7248
|
||||
ewan=\u76CA\u73A9\u7248
|
||||
huawei=\u534E\u4E3A\u7248
|
||||
gf-h=\u5B98\u65B9-\u4E13\u670D\u7248
|
||||
gf-z=\u5B98\u65B9-\u6DF7\u670D\u7248
|
||||
shuizhu=\u6C34\u716E\u7248
|
||||
jifeng=\u673A\u950B\u7248
|
||||
azsc=\u5B89\u5353\u5E02\u573A\u7248
|
||||
lenvono=\u8054\u60F3\u7248
|
||||
jinshan=\u91D1\u5C71\u7248
|
||||
mumayi=\u6728\u8682\u8681\u7248
|
||||
gf-n=\u5B98\u7F51-\u5185\u7248
|
||||
gf-w=\u5B98\u7F51-\u5916\u7248
|
||||
duoku=\u591A\u9177\u7248
|
||||
pptv=PPTV\u7248
|
||||
\u5B98\u65B9\u7248=\u5B98\u65B9\u7248
|
||||
\u5B98\u65B9=\u5B98\u65B9\u7248
|
||||
@ -1,652 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Wasabeef
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// alert("")
|
||||
|
||||
var RE = {};
|
||||
|
||||
RE.currentSelection = {
|
||||
"startContainer": 0,
|
||||
"startOffset": 0,
|
||||
"endContainer": 0,
|
||||
"endOffset": 0};
|
||||
|
||||
var isDebug = false;
|
||||
try {
|
||||
isDebug = window.NativeCallBack.isNativeBuildDebug()
|
||||
} catch(error) {
|
||||
}
|
||||
|
||||
// 引用远端的JS 和 CSS
|
||||
var script = document.createElement("script")
|
||||
document.body.appendChild(script)
|
||||
if (isDebug) {
|
||||
script.src = "https://dev-and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
|
||||
} else {
|
||||
script.src = "https://and-static.ghzs66.com/web/js/halo.js" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
|
||||
}
|
||||
|
||||
var style = document.createElement("link")
|
||||
style.rel = "stylesheet"
|
||||
style.type = "text/css"
|
||||
if (isDebug) {
|
||||
style.href = "https://dev-and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000)
|
||||
} else {
|
||||
style.href = "https://and-static.ghzs66.com/web/css/halo.css" + "?timestamp=" + Math.round(new Date().getTime() / 1000 / 1000)
|
||||
}
|
||||
|
||||
document.head.appendChild(style)
|
||||
|
||||
RE.editor = document.getElementById('editor');
|
||||
|
||||
document.addEventListener("selectionchange", function() { RE.backuprange(); });
|
||||
|
||||
// Initializations
|
||||
RE.callback = function() {
|
||||
window.location.href = "re-callback://" + encodeURIComponent(RE.getHtml());
|
||||
}
|
||||
|
||||
RE.setHtml = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// 后续初始化html代码,都用该方法
|
||||
RE.setHtmlByVideoStatus = function(contents) {
|
||||
RE.editor.innerHTML = decodeURIComponent(contents.replace(/\+/g, '%20'));
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
RE.getHtml = function() {
|
||||
return RE.editor.innerHTML;
|
||||
}
|
||||
|
||||
RE.getText = function() {
|
||||
return RE.editor.innerText;
|
||||
}
|
||||
|
||||
RE.setBaseTextColor = function(color) {
|
||||
RE.editor.style.color = color;
|
||||
}
|
||||
|
||||
RE.setBaseFontSize = function(size) {
|
||||
RE.editor.style.fontSize = size;
|
||||
}
|
||||
|
||||
RE.setPadding = function(left, top, right, bottom) {
|
||||
RE.editor.style.paddingLeft = left;
|
||||
RE.editor.style.paddingTop = top;
|
||||
RE.editor.style.paddingRight = right;
|
||||
RE.editor.style.paddingBottom = bottom;
|
||||
}
|
||||
|
||||
RE.setBackgroundColor = function(color) {
|
||||
document.body.style.backgroundColor = color;
|
||||
}
|
||||
|
||||
RE.setBackgroundImage = function(image) {
|
||||
RE.editor.style.backgroundImage = image;
|
||||
}
|
||||
|
||||
RE.setWidth = function(size) {
|
||||
RE.editor.style.minWidth = size;
|
||||
}
|
||||
|
||||
RE.setHeight = function(size) {
|
||||
RE.editor.style.height = size;
|
||||
}
|
||||
|
||||
RE.setTextAlign = function(align) {
|
||||
RE.editor.style.textAlign = align;
|
||||
}
|
||||
|
||||
RE.setVerticalAlign = function(align) {
|
||||
RE.editor.style.verticalAlign = align;
|
||||
}
|
||||
|
||||
RE.setPlaceholder = function(placeholder) {
|
||||
RE.editor.setAttribute("placeholder", placeholder);
|
||||
}
|
||||
|
||||
RE.setEditorFocus = function() {
|
||||
RE.editor.focus();
|
||||
}
|
||||
|
||||
RE.setInputEnabled = function(inputEnabled) {
|
||||
RE.editor.contentEditable = String(inputEnabled);
|
||||
}
|
||||
|
||||
RE.formatBlock = function() {
|
||||
document.execCommand('formatBlock', false, 'p');
|
||||
}
|
||||
|
||||
RE.undo = function() {
|
||||
document.execCommand('undo', false, null);
|
||||
}
|
||||
|
||||
RE.redo = function() {
|
||||
document.execCommand('redo', false, null);
|
||||
}
|
||||
|
||||
RE.setBold = function() {
|
||||
document.execCommand('bold', false, null);
|
||||
}
|
||||
|
||||
RE.setItalic = function() {
|
||||
document.execCommand('italic', false, null);
|
||||
}
|
||||
|
||||
RE.setSubscript = function() {
|
||||
document.execCommand('subscript', false, null);
|
||||
}
|
||||
|
||||
RE.setSuperscript = function() {
|
||||
document.execCommand('superscript', false, null);
|
||||
}
|
||||
|
||||
RE.setStrikeThrough = function() {
|
||||
document.execCommand('strikeThrough', false, null);
|
||||
}
|
||||
|
||||
RE.setUnderline = function() {
|
||||
document.execCommand('underline', false, null);
|
||||
}
|
||||
|
||||
RE.setBullets = function() {
|
||||
document.execCommand('insertUnorderedList', false, null);
|
||||
}
|
||||
|
||||
RE.setNumbers = function() {
|
||||
document.execCommand('insertOrderedList', false, null);
|
||||
}
|
||||
|
||||
RE.setTextColor = function(color) {
|
||||
RE.restorerange();
|
||||
document.execCommand("styleWithCSS", null, true);
|
||||
document.execCommand('foreColor', false, color);
|
||||
document.execCommand("styleWithCSS", null, false);
|
||||
}
|
||||
|
||||
RE.setTextBackgroundColor = function(color) {
|
||||
RE.restorerange();
|
||||
document.execCommand("styleWithCSS", null, true);
|
||||
document.execCommand('hiliteColor', false, color);
|
||||
document.execCommand("styleWithCSS", null, false);
|
||||
}
|
||||
|
||||
RE.setFontSize = function(fontSize){
|
||||
document.execCommand("fontSize", false, fontSize);
|
||||
}
|
||||
|
||||
RE.setHeading = function(heading) {
|
||||
document.execCommand('formatBlock', false, '<h'+heading+'>');
|
||||
RE.sendElementNameToNative()
|
||||
}
|
||||
|
||||
RE.setIndent = function() {
|
||||
document.execCommand('indent', false, null);
|
||||
}
|
||||
|
||||
RE.setOutdent = function() {
|
||||
document.execCommand('outdent', false, null);
|
||||
}
|
||||
|
||||
RE.setJustifyLeft = function() {
|
||||
document.execCommand('justifyLeft', false, null);
|
||||
RE.enabledEditingItems()
|
||||
}
|
||||
|
||||
RE.setJustifyCenter = function() {
|
||||
document.execCommand('justifyCenter', false, null);
|
||||
RE.enabledEditingItems()
|
||||
}
|
||||
|
||||
RE.setJustifyRight = function() {
|
||||
document.execCommand('justifyRight', false, null);
|
||||
RE.enabledEditingItems()
|
||||
}
|
||||
|
||||
RE.setBlockquote = function() {
|
||||
document.execCommand('formatBlock', false, '<blockquote>');
|
||||
// var blockId = window.getSelection().focusNode.parentNode;
|
||||
// $(blockId).addClass("haloBlock")
|
||||
RE.sendElementNameToNative()
|
||||
}
|
||||
|
||||
RE.insertImage = function(url) {
|
||||
var html = "<div><img src =\"" + url + "\" style=\" max-width: 100%; display:block; margin:15px auto; height: auto;\"></div><br>"
|
||||
RE.insertHTML(html);
|
||||
}
|
||||
|
||||
// 设置分割线
|
||||
RE.insertHorizontalRule = function() {
|
||||
document.execCommand('insertHorizontalRule', false, null);
|
||||
}
|
||||
|
||||
// 设置编辑器默认换行符
|
||||
RE.setDefaultParagraphSeparator = function(separator) {
|
||||
document.execCommand('defaultParagraphSeparator', false, separator);
|
||||
}
|
||||
|
||||
// 替换成缩略图
|
||||
RE.replaceTbImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
var index = 0
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
// console.log(imageClassName)
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("?") > 0) continue;
|
||||
// console.log(i)
|
||||
var tbImg
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
tbImg = img.src + gifRuleFlag
|
||||
} else {
|
||||
tbImg = img.src + imgRuleFlag
|
||||
}
|
||||
|
||||
img.style.cssText = "max-width: 60%; display:block; margin:15px auto; height: auto;"
|
||||
img.src = tbImg;
|
||||
|
||||
if (index == 0) {
|
||||
var bigImg = document.createElement('img');
|
||||
bigImg.src = "file:///android_asset/web_load_dfimg_icon.png";
|
||||
bigImg.style.cssText = "max-width: 20%; margin:15px 0 0 0; height: auto;"
|
||||
img.parentNode.insertBefore(bigImg, img.parentNode.childNodes[0]);
|
||||
i++;
|
||||
|
||||
if(img.parentNode != null) {
|
||||
img.parentNode.style.cssText += "text-align: left;"
|
||||
}
|
||||
|
||||
if(img.parentNode != null && img.parentNode.parentNode != null) {
|
||||
img.parentNode.parentNode.style.cssText += "text-align: left;"
|
||||
}
|
||||
|
||||
}
|
||||
index ++;
|
||||
}
|
||||
}
|
||||
|
||||
// 替换成默认图
|
||||
RE.replaceAllDfImage = function(imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
i--;
|
||||
} else {
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
img.src = img.src.split("?")[0] + gifRuleFlag
|
||||
} else {
|
||||
img.src = img.src.split("?")[0] + imgRuleFlag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 去除显示大图
|
||||
RE.hideShowBigPic = function() {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
var j = 0;
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if (img.src.indexOf(".gif") == -1) {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
// 去除显示大图
|
||||
if (j == 0) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if(img.src.indexOf("web_load_dfimg_icon") > 0) {
|
||||
img.parentNode.removeChild(img.parentNode.childNodes[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RE.replaceDfImageByUrl = function(imgUrl, imgRuleFlag, gifRuleFlag) {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link" || img.className == "poster") continue;
|
||||
if (img.src.indexOf(imgUrl) != -1) {
|
||||
if(img.src.indexOf(".gif") > 0) {
|
||||
img.src = img.src.split("?")[0] + gifRuleFlag
|
||||
} else {
|
||||
img.src = img.src.split("?")[0] + imgRuleFlag
|
||||
}
|
||||
}
|
||||
}
|
||||
RE.hideShowBigPic();
|
||||
}
|
||||
|
||||
RE.ImageClickListener = function() {
|
||||
var imgs = document.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
var imageClassName = img.className;
|
||||
if (imageClassName == "image-link"|| img.className == "poster") continue;
|
||||
window.imagelistener.imageArr(img.src);
|
||||
img.onclick = function() {
|
||||
window.imagelistener.imageClick(this.src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RE.insertHTML = function(html) {
|
||||
RE.restorerange();
|
||||
document.execCommand('insertHTML', false, html);
|
||||
}
|
||||
|
||||
RE.insertLink = function(url, title) {
|
||||
RE.restorerange();
|
||||
var sel = document.getSelection();
|
||||
if (sel.toString().length == 0) {
|
||||
document.execCommand("insertHTML",false,"<a href='"+url+"'>"+title+"</a>");
|
||||
} else if (sel.rangeCount) {
|
||||
var el = document.createElement("a");
|
||||
el.setAttribute("href", url);
|
||||
el.setAttribute("title", title);
|
||||
|
||||
var range = sel.getRangeAt(0).cloneRange();
|
||||
range.surroundContents(el);
|
||||
sel.removeAllRanges();
|
||||
sel.addRange(range);
|
||||
}
|
||||
RE.callback();
|
||||
}
|
||||
|
||||
RE.setTodo = function(text) {
|
||||
var html = '<input type="checkbox" name="'+ text +'" value="'+ text +'"/> ';
|
||||
document.execCommand('insertHTML', false, html);
|
||||
}
|
||||
|
||||
RE.prepareInsert = function() {
|
||||
RE.backuprange();
|
||||
}
|
||||
|
||||
RE.backuprange = function(){
|
||||
var selection = window.getSelection();
|
||||
if (selection.rangeCount > 0) {
|
||||
var range = selection.getRangeAt(0);
|
||||
RE.currentSelection = {
|
||||
"startContainer": range.startContainer,
|
||||
"startOffset": range.startOffset,
|
||||
"endContainer": range.endContainer,
|
||||
"endOffset": range.endOffset};
|
||||
}
|
||||
}
|
||||
|
||||
RE.restorerange = function(){
|
||||
try {
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
var range = document.createRange();
|
||||
range.setStart(RE.currentSelection.startContainer, RE.currentSelection.startOffset);
|
||||
range.setEnd(RE.currentSelection.endContainer, RE.currentSelection.endOffset);
|
||||
selection.addRange(range);
|
||||
} catch(error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
RE.enabledEditingItems = function(e) {
|
||||
var items = [];
|
||||
if (document.queryCommandState('bold')) {
|
||||
items.push('bold');
|
||||
}
|
||||
if (document.queryCommandState('italic')) {
|
||||
items.push('italic');
|
||||
}
|
||||
if (document.queryCommandState('subscript')) {
|
||||
items.push('subscript');
|
||||
}
|
||||
if (document.queryCommandState('superscript')) {
|
||||
items.push('superscript');
|
||||
}
|
||||
if (document.queryCommandState('strikeThrough')) {
|
||||
items.push('strikeThrough');
|
||||
}
|
||||
if (document.queryCommandState('underline')) {
|
||||
items.push('underline');
|
||||
}
|
||||
if (document.queryCommandState('insertOrderedList')) {
|
||||
items.push('orderedList');
|
||||
}
|
||||
if (document.queryCommandState('insertUnorderedList')) {
|
||||
items.push('unorderedList');
|
||||
}
|
||||
if (document.queryCommandState('justifyCenter')) {
|
||||
items.push('justifyCenter');
|
||||
}
|
||||
if (document.queryCommandState('justifyFull')) {
|
||||
items.push('justifyFull');
|
||||
}
|
||||
if (document.queryCommandState('justifyLeft')) {
|
||||
items.push('justifyLeft');
|
||||
}
|
||||
if (document.queryCommandState('justifyRight')) {
|
||||
items.push('justifyRight');
|
||||
}
|
||||
if (document.queryCommandState('insertHorizontalRule')) {
|
||||
items.push('horizontalRule');
|
||||
}
|
||||
var formatBlock = document.queryCommandValue('formatBlock');
|
||||
if (formatBlock.length > 0) {
|
||||
items.push(formatBlock);
|
||||
}
|
||||
|
||||
window.location.href = "re-state://" + encodeURI(items.join(','));
|
||||
}
|
||||
|
||||
RE.focus = function() {
|
||||
var range = document.createRange();
|
||||
range.selectNodeContents(RE.editor);
|
||||
range.collapse(false);
|
||||
var selection = window.getSelection();
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
RE.editor.focus();
|
||||
}
|
||||
|
||||
RE.blurFocus = function() {
|
||||
RE.editor.blur();
|
||||
}
|
||||
|
||||
RE.removeFormat = function() {
|
||||
document.execCommand('removeFormat', false, null);
|
||||
}
|
||||
|
||||
RE.insertCustomStyleLink = function(data) {
|
||||
var entity = JSON.parse(data)
|
||||
var html = "<br/><div class='"+ entity.type +"-container'>\n" +
|
||||
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
|
||||
" <div class='flex-container'>\n" +
|
||||
" <div class='gh-internal-content img-left'>\n" +
|
||||
" <img class = \"image-link\" src='"+ entity.icon +"' />\n" +
|
||||
" </div>\n" +
|
||||
" <div class='gh-internal-content content-right'>\n" +
|
||||
" <p class='content-title'>"+ entity.title +"</p>\n" +
|
||||
" <p class='contents'>"+ entity.brief +"</p>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </a>\n" +
|
||||
" </div><br/>"
|
||||
var tags = "", gameHtml = ""
|
||||
if (entity.tags != null) {
|
||||
for (var i = 0; i < entity.tags.length; i++) {
|
||||
tags += "<label>"+ entity.tags[i]+"</label>"
|
||||
}
|
||||
|
||||
gameHtml = "<br/><div class='"+ entity.type +"-container'>\n" +
|
||||
" <a class='"+ entity.type +"' href=\"javascript:void(0);\" contenteditable=\"false\" onclick=\"customLinkgo(this)\" data-datas='"+ data +"'>\n" +
|
||||
" <div class='flex-container'>\n" +
|
||||
" <div class='gh-internal-content img-left'>\n" +
|
||||
" <img class='image-link' src='"+ entity.icon +"' />\n" +
|
||||
" </div>\n" +
|
||||
" <div class='gh-internal-content content-right'>\n" +
|
||||
" <p class='content-title'>"+ entity.title +"</p>\n" +
|
||||
" <p class='tags'>"+ tags +"</p>\n" +
|
||||
" </div>\n" +
|
||||
" </div>\n" +
|
||||
" </a></div><br/>"
|
||||
}
|
||||
|
||||
switch(entity.type) {
|
||||
case "answer":
|
||||
document.execCommand("insertHTML",false, html);
|
||||
break
|
||||
case "community_article":
|
||||
document.execCommand("insertHTML",false, html);
|
||||
break
|
||||
case "game":
|
||||
document.execCommand("insertHTML",false, gameHtml);
|
||||
break
|
||||
}
|
||||
RE.callback();
|
||||
}
|
||||
|
||||
RE.showLinkStyle = function() {
|
||||
var answerElement = document.getElementsByClassName("answer-container");
|
||||
for (var i=0;i<answerElement.length;i+=1){
|
||||
answerElement[i].style.display = 'inline';
|
||||
}
|
||||
var articleElement = document.getElementsByClassName("community_article-container");
|
||||
for (var i=0;i<articleElement.length;i+=1){
|
||||
articleElement[i].style.display = 'inline';
|
||||
}
|
||||
var gameElement = document.getElementsByClassName("game-container");
|
||||
for (var i=0;i<gameElement.length;i+=1){
|
||||
gameElement[i].style.display = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
RE.hideLinkStyle = function() {
|
||||
var answerElement = document.getElementsByClassName("answer-container");
|
||||
for (var i=0;i<answerElement.length;i+=1){
|
||||
answerElement[i].style.display = 'none';
|
||||
}
|
||||
var articleElement = document.getElementsByClassName("community_article-container");
|
||||
for (var i=0;i<articleElement.length;i+=1){
|
||||
articleElement[i].style.display = 'none';
|
||||
}
|
||||
var gameElement = document.getElementsByClassName("game-container");
|
||||
for (var i=0;i<gameElement.length;i+=1){
|
||||
gameElement[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Event Listeners
|
||||
RE.editor.addEventListener("input", RE.callback);
|
||||
|
||||
RE.editor.addEventListener("keyup", function(e) {
|
||||
var KEY_LEFT = 37, KEY_RIGHT = 39;
|
||||
if (e.which == KEY_LEFT || e.which == KEY_RIGHT) {
|
||||
RE.enabledEditingItems(e);
|
||||
}
|
||||
RE.sendElementNameToNative()
|
||||
});
|
||||
|
||||
RE.editor.addEventListener("click", function(e) {
|
||||
RE.enabledEditingItems
|
||||
RE.sendElementNameToNative()
|
||||
var s = document.getSelection()
|
||||
var isNeedRemoveR = RE.recursion(e.target)
|
||||
if (isNeedRemoveR && s.rangeCount) {
|
||||
s.removeAllRanges()
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
RE.sendElementNameToNative()
|
||||
});
|
||||
|
||||
document.addEventListener("selectionchange", function(e) {
|
||||
setTimeout(() => RE.enabledEditingItems(e), 10)
|
||||
});
|
||||
|
||||
RE.recursion = function(dom) {
|
||||
var parenDom = dom.parentElement
|
||||
if (parenDom && parenDom instanceof Element &&
|
||||
typeClassList.indexOf(parenDom.className) > -1) {
|
||||
return parenDom
|
||||
} else if(parenDom && parenDom instanceof Element &&
|
||||
typeClassList.indexOf(parenDom.className) === -1 && parenDom.nodeName !== 'BODY') {
|
||||
return RE.recursion(parenDom)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
// 返回组件标签 多个标签以"空格"划分
|
||||
RE.sendElementNameToNative = function() {
|
||||
if (window.getSelection) {
|
||||
var selection = window.getSelection()
|
||||
if (selection.rangeCount > 0) {
|
||||
var range = selection.getRangeAt(0);
|
||||
var container = range.startContainer;
|
||||
var elements = " " + container.localName + " ";
|
||||
var parentElement;
|
||||
while(true) {
|
||||
if(parentElement != null) {
|
||||
parentElement = parentElement.parentElement
|
||||
} else {
|
||||
parentElement = container.parentElement
|
||||
}
|
||||
if (parentElement == null || parentElement.localName == null) {
|
||||
break;
|
||||
}
|
||||
elements = elements + " " + parentElement.localName + " "
|
||||
}
|
||||
// console.log(elements)
|
||||
window.OnCursorChangeListener.onElements(elements);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// android function to open link
|
||||
function customLinkgo(self) {
|
||||
var datas = self.dataset.datas
|
||||
window.OnLinkClickListener.onClick(datas)
|
||||
}
|
||||
|
||||
// 在web页面播放视频
|
||||
//RE.initArticleVideo = function(){
|
||||
// initArticleVideo()
|
||||
//}
|
||||
|
||||
function showNativeDialog(title, message, positive, negative, callback) {
|
||||
var jsCallbackCode = "(" + function (v) {
|
||||
window.onNativeDialogCallback(v);
|
||||
delete window.onNativeDialogCallback;
|
||||
}.toString() + ")";
|
||||
|
||||
window.onNativeDialogCallback = callback;
|
||||
window.NativeCallBack.showDialog(title, message, positive, negative, jsCallbackCode);
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2017 Wasabeef
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
@charset "UTF-8";
|
||||
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
overflow: scroll;
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
min-height:100%;
|
||||
}
|
||||
|
||||
#editor {
|
||||
outline: 0px solid transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
#editor[placeholder]:empty:not(:focus):before {
|
||||
content: attr(placeholder);
|
||||
opacity: .5;
|
||||
}}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.8 KiB |
2
app/src/main/assets/zepto.min.js
vendored
2
app/src/main/assets/zepto.min.js
vendored
File diff suppressed because one or more lines are too long
697
app/src/main/java/android/support/v7/widget/AdapterHelper.java
Normal file
697
app/src/main/java/android/support/v7/widget/AdapterHelper.java
Normal file
@ -0,0 +1,697 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.support.v4.util.Pools;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
|
||||
/**
|
||||
* Helper class that can enqueue and process adapter update operations.
|
||||
* <p>
|
||||
* To support animations, RecyclerView presents an older version the Adapter to best represent
|
||||
* previous state of the layout. Sometimes, this is not trivial when items are removed that were
|
||||
* not laid out, in which case, RecyclerView has no way of providing that item's view for
|
||||
* animations.
|
||||
* <p>
|
||||
* AdapterHelper creates an UpdateOp for each adapter data change then pre-processes them. During
|
||||
* pre processing, AdapterHelper finds out which UpdateOps can be deferred to second layout pass
|
||||
* and which cannot. For the UpdateOps that cannot be deferred, AdapterHelper will change them
|
||||
* according to previously deferred operation and dispatch them before the first layout pass. It
|
||||
* also takes care of updating deferred UpdateOps since order of operations is changed by this
|
||||
* process.
|
||||
* <p>
|
||||
* Although operations may be forwarded to LayoutManager in different orders, resulting data set
|
||||
* is guaranteed to be the consistent.
|
||||
*/
|
||||
class AdapterHelper implements OpReorderer.Callback {
|
||||
|
||||
final static int POSITION_TYPE_INVISIBLE = 0;
|
||||
|
||||
final static int POSITION_TYPE_NEW_OR_LAID_OUT = 1;
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String TAG = "AHT";
|
||||
|
||||
private Pools.Pool<UpdateOp> mUpdateOpPool = new Pools.SimplePool<UpdateOp>(UpdateOp.POOL_SIZE);
|
||||
|
||||
final ArrayList<UpdateOp> mPendingUpdates = new ArrayList<UpdateOp>();
|
||||
|
||||
final ArrayList<UpdateOp> mPostponedList = new ArrayList<UpdateOp>();
|
||||
|
||||
final Callback mCallback;
|
||||
|
||||
Runnable mOnItemProcessedCallback;
|
||||
|
||||
final boolean mDisableRecycler;
|
||||
|
||||
final OpReorderer mOpReorderer;
|
||||
|
||||
AdapterHelper(Callback callback) {
|
||||
this(callback, false);
|
||||
}
|
||||
|
||||
AdapterHelper(Callback callback, boolean disableRecycler) {
|
||||
mCallback = callback;
|
||||
mDisableRecycler = disableRecycler;
|
||||
mOpReorderer = new OpReorderer(this);
|
||||
}
|
||||
|
||||
AdapterHelper addUpdateOp(UpdateOp... ops) {
|
||||
Collections.addAll(mPendingUpdates, ops);
|
||||
return this;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
recycleUpdateOpsAndClearList(mPendingUpdates);
|
||||
recycleUpdateOpsAndClearList(mPostponedList);
|
||||
}
|
||||
|
||||
void preProcess() {
|
||||
mOpReorderer.reorderOps(mPendingUpdates);
|
||||
final int count = mPendingUpdates.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPendingUpdates.get(i);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
applyAdd(op);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
applyRemove(op);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
applyUpdate(op);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
applyMove(op);
|
||||
break;
|
||||
}
|
||||
if (mOnItemProcessedCallback != null) {
|
||||
mOnItemProcessedCallback.run();
|
||||
}
|
||||
}
|
||||
mPendingUpdates.clear();
|
||||
}
|
||||
|
||||
void consumePostponedUpdates() {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
mCallback.onDispatchSecondPass(mPostponedList.get(i));
|
||||
}
|
||||
recycleUpdateOpsAndClearList(mPostponedList);
|
||||
}
|
||||
|
||||
private void applyMove(UpdateOp op) {
|
||||
// MOVE ops are pre-processed so at this point, we know that item is still in the adapter.
|
||||
// otherwise, it would be converted into a REMOVE operation
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
|
||||
private void applyRemove(UpdateOp op) {
|
||||
int tmpStart = op.positionStart;
|
||||
int tmpCount = 0;
|
||||
int tmpEnd = op.positionStart + op.itemCount;
|
||||
int type = -1;
|
||||
for (int position = op.positionStart; position < tmpEnd; position++) {
|
||||
boolean typeChanged = false;
|
||||
ViewHolder vh = mCallback.findViewHolder(position);
|
||||
if (vh != null || canFindInPreLayout(position)) {
|
||||
// If a ViewHolder exists or this is a newly added item, we can defer this update
|
||||
// to post layout stage.
|
||||
// * For existing ViewHolders, we'll fake its existence in the pre-layout phase.
|
||||
// * For items that are added and removed in the same process cycle, they won't
|
||||
// have any effect in pre-layout since their add ops are already deferred to
|
||||
// post-layout pass.
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
// Looks like we have other updates that we cannot merge with this one.
|
||||
// Create an UpdateOp and dispatch it to LayoutManager.
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
dispatchAndUpdateViewHolders(newOp);
|
||||
typeChanged = true;
|
||||
}
|
||||
type = POSITION_TYPE_NEW_OR_LAID_OUT;
|
||||
} else {
|
||||
// This update cannot be recovered because we don't have a ViewHolder representing
|
||||
// this position. Instead, post it to LayoutManager immediately
|
||||
if (type == POSITION_TYPE_NEW_OR_LAID_OUT) {
|
||||
// Looks like we have other updates that we cannot merge with this one.
|
||||
// Create UpdateOp op and dispatch it to LayoutManager.
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
postponeAndUpdateViewHolders(newOp);
|
||||
typeChanged = true;
|
||||
}
|
||||
type = POSITION_TYPE_INVISIBLE;
|
||||
}
|
||||
if (typeChanged) {
|
||||
position -= tmpCount; // also equal to tmpStart
|
||||
tmpEnd -= tmpCount;
|
||||
tmpCount = 1;
|
||||
} else {
|
||||
tmpCount++;
|
||||
}
|
||||
}
|
||||
if (tmpCount != op.itemCount) { // all 1 effect
|
||||
recycleUpdateOp(op);
|
||||
op = obtainUpdateOp(UpdateOp.REMOVE, tmpStart, tmpCount);
|
||||
}
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
dispatchAndUpdateViewHolders(op);
|
||||
} else {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
}
|
||||
|
||||
private void applyUpdate(UpdateOp op) {
|
||||
int tmpStart = op.positionStart;
|
||||
int tmpCount = 0;
|
||||
int tmpEnd = op.positionStart + op.itemCount;
|
||||
int type = -1;
|
||||
for (int position = op.positionStart; position < tmpEnd; position++) {
|
||||
ViewHolder vh = mCallback.findViewHolder(position);
|
||||
if (vh != null || canFindInPreLayout(position)) { // deferred
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
dispatchAndUpdateViewHolders(newOp);
|
||||
tmpCount = 0;
|
||||
tmpStart = position;
|
||||
}
|
||||
type = POSITION_TYPE_NEW_OR_LAID_OUT;
|
||||
} else { // applied
|
||||
if (type == POSITION_TYPE_NEW_OR_LAID_OUT) {
|
||||
UpdateOp newOp = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
postponeAndUpdateViewHolders(newOp);
|
||||
tmpCount = 0;
|
||||
tmpStart = position;
|
||||
}
|
||||
type = POSITION_TYPE_INVISIBLE;
|
||||
}
|
||||
tmpCount++;
|
||||
}
|
||||
if (tmpCount != op.itemCount) { // all 1 effect
|
||||
recycleUpdateOp(op);
|
||||
op = obtainUpdateOp(UpdateOp.UPDATE, tmpStart, tmpCount);
|
||||
}
|
||||
if (type == POSITION_TYPE_INVISIBLE) {
|
||||
dispatchAndUpdateViewHolders(op);
|
||||
} else {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
}
|
||||
|
||||
private void dispatchAndUpdateViewHolders(UpdateOp op) {
|
||||
// tricky part.
|
||||
// traverse all postpones and revert their changes on this op if necessary, apply updated
|
||||
// dispatch to them since now they are after this op.
|
||||
if (op.cmd == UpdateOp.ADD || op.cmd == UpdateOp.MOVE) {
|
||||
throw new IllegalArgumentException("should not dispatch add or move for pre layout");
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispatch (pre)" + op);
|
||||
Log.d(TAG, "postponed state before:");
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
|
||||
// handle each pos 1 by 1 to ensure continuity. If it breaks, dispatch partial
|
||||
// TODO Since move ops are pushed to end, we should not need this anymore
|
||||
int tmpStart = updatePositionWithPostponed(op.positionStart, op.cmd);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "pos:" + op.positionStart + ",updatedPos:" + tmpStart);
|
||||
}
|
||||
int tmpCnt = 1;
|
||||
int offsetPositionForPartial = op.positionStart;
|
||||
final int positionMultiplier;
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.UPDATE:
|
||||
positionMultiplier = 1;
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
positionMultiplier = 0;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("op should be remove or update." + op);
|
||||
}
|
||||
for (int p = 1; p < op.itemCount; p++) {
|
||||
final int pos = op.positionStart + (positionMultiplier * p);
|
||||
int updatedPos = updatePositionWithPostponed(pos, op.cmd);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "pos:" + pos + ",updatedPos:" + updatedPos);
|
||||
}
|
||||
boolean continuous = false;
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.UPDATE:
|
||||
continuous = updatedPos == tmpStart + 1;
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
continuous = updatedPos == tmpStart;
|
||||
break;
|
||||
}
|
||||
if (continuous) {
|
||||
tmpCnt++;
|
||||
} else {
|
||||
// need to dispatch this separately
|
||||
UpdateOp tmp = obtainUpdateOp(op.cmd, tmpStart, tmpCnt);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "need to dispatch separately " + tmp);
|
||||
}
|
||||
dispatchFirstPassAndUpdateViewHolders(tmp, offsetPositionForPartial);
|
||||
recycleUpdateOp(tmp);
|
||||
if (op.cmd == UpdateOp.UPDATE) {
|
||||
offsetPositionForPartial += tmpCnt;
|
||||
}
|
||||
tmpStart = updatedPos;// need to remove previously dispatched
|
||||
tmpCnt = 1;
|
||||
}
|
||||
}
|
||||
recycleUpdateOp(op);
|
||||
if (tmpCnt > 0) {
|
||||
UpdateOp tmp = obtainUpdateOp(op.cmd, tmpStart, tmpCnt);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispatching:" + tmp);
|
||||
}
|
||||
dispatchFirstPassAndUpdateViewHolders(tmp, offsetPositionForPartial);
|
||||
recycleUpdateOp(tmp);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "post dispatch");
|
||||
Log.d(TAG, "postponed state after:");
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
}
|
||||
|
||||
void dispatchFirstPassAndUpdateViewHolders(UpdateOp op, int offsetStart) {
|
||||
mCallback.onDispatchFirstPass(op);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.offsetPositionsForRemovingInvisible(offsetStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.markViewHoldersUpdated(offsetStart, op.itemCount);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("only remove and update ops can be dispatched"
|
||||
+ " in first pass");
|
||||
}
|
||||
}
|
||||
|
||||
private int updatePositionWithPostponed(int pos, int cmd) {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
UpdateOp postponed = mPostponedList.get(i);
|
||||
if (postponed.cmd == UpdateOp.MOVE) {
|
||||
int start, end;
|
||||
if (postponed.positionStart < postponed.itemCount) {
|
||||
start = postponed.positionStart;
|
||||
end = postponed.itemCount;
|
||||
} else {
|
||||
start = postponed.itemCount;
|
||||
end = postponed.positionStart;
|
||||
}
|
||||
if (pos >= start && pos <= end) {
|
||||
//i'm affected
|
||||
if (start == postponed.positionStart) {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.itemCount++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.itemCount--;
|
||||
}
|
||||
// op moved to left, move it right to revert
|
||||
pos++;
|
||||
} else {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
}
|
||||
// op was moved right, move left to revert
|
||||
pos--;
|
||||
}
|
||||
} else if (pos < postponed.positionStart) {
|
||||
// postponed MV is outside the dispatched OP. if it is before, offset
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
postponed.itemCount++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
postponed.itemCount--;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (postponed.positionStart <= pos) {
|
||||
if (postponed.cmd == UpdateOp.ADD) {
|
||||
pos -= postponed.itemCount;
|
||||
} else if (postponed.cmd == UpdateOp.REMOVE) {
|
||||
pos += postponed.itemCount;
|
||||
}
|
||||
} else {
|
||||
if (cmd == UpdateOp.ADD) {
|
||||
postponed.positionStart++;
|
||||
} else if (cmd == UpdateOp.REMOVE) {
|
||||
postponed.positionStart--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "dispath (step" + i + ")");
|
||||
Log.d(TAG, "postponed state:" + i + ", pos:" + pos);
|
||||
for (UpdateOp updateOp : mPostponedList) {
|
||||
Log.d(TAG, updateOp.toString());
|
||||
}
|
||||
Log.d(TAG, "----");
|
||||
}
|
||||
}
|
||||
for (int i = mPostponedList.size() - 1; i >= 0; i--) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (op.itemCount == op.positionStart || op.itemCount < 0) {
|
||||
mPostponedList.remove(i);
|
||||
recycleUpdateOp(op);
|
||||
}
|
||||
} else if (op.itemCount <= 0) {
|
||||
mPostponedList.remove(i);
|
||||
recycleUpdateOp(op);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private boolean canFindInPreLayout(int position) {
|
||||
final int count = mPostponedList.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (findPositionOffset(op.itemCount, i + 1) == position) {
|
||||
return true;
|
||||
}
|
||||
} else if (op.cmd == UpdateOp.ADD) {
|
||||
// TODO optimize.
|
||||
final int end = op.positionStart + op.itemCount;
|
||||
for (int pos = op.positionStart; pos < end; pos++) {
|
||||
if (findPositionOffset(pos, i + 1) == position) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void applyAdd(UpdateOp op) {
|
||||
postponeAndUpdateViewHolders(op);
|
||||
}
|
||||
|
||||
private void postponeAndUpdateViewHolders(UpdateOp op) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "postponing " + op);
|
||||
}
|
||||
mPostponedList.add(op);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
mCallback.offsetPositionsForAdd(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
mCallback.offsetPositionsForMove(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.offsetPositionsForRemovingLaidOutOrNewView(op.positionStart,
|
||||
op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown update op type for " + op);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasPendingUpdates() {
|
||||
return mPendingUpdates.size() > 0;
|
||||
}
|
||||
|
||||
int findPositionOffset(int position) {
|
||||
return findPositionOffset(position, 0);
|
||||
}
|
||||
|
||||
int findPositionOffset(int position, int firstPostponedItem) {
|
||||
int count = mPostponedList.size();
|
||||
for (int i = firstPostponedItem; i < count; ++i) {
|
||||
UpdateOp op = mPostponedList.get(i);
|
||||
if (op.cmd == UpdateOp.MOVE) {
|
||||
if (op.positionStart == position) {
|
||||
position = op.itemCount;
|
||||
} else {
|
||||
if (op.positionStart < position) {
|
||||
position--; // like a remove
|
||||
}
|
||||
if (op.itemCount <= position) {
|
||||
position++; // like an add
|
||||
}
|
||||
}
|
||||
} else if (op.positionStart <= position) {
|
||||
if (op.cmd == UpdateOp.REMOVE) {
|
||||
if (position < op.positionStart + op.itemCount) {
|
||||
return -1;
|
||||
}
|
||||
position -= op.itemCount;
|
||||
} else if (op.cmd == UpdateOp.ADD) {
|
||||
position += op.itemCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeChanged(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.UPDATE, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeInserted(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.ADD, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeRemoved(int positionStart, int itemCount) {
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.REMOVE, positionStart, itemCount));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return True if updates should be processed.
|
||||
*/
|
||||
boolean onItemRangeMoved(int from, int to, int itemCount) {
|
||||
if (from == to) {
|
||||
return false;//no-op
|
||||
}
|
||||
if (itemCount != 1) {
|
||||
throw new IllegalArgumentException("Moving more than 1 item is not supported yet");
|
||||
}
|
||||
mPendingUpdates.add(obtainUpdateOp(UpdateOp.MOVE, from, to));
|
||||
return mPendingUpdates.size() == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips pre-processing and applies all updates in one pass.
|
||||
*/
|
||||
void consumeUpdatesInOnePass() {
|
||||
// we still consume postponed updates (if there is) in case there was a pre-process call
|
||||
// w/o a matching consumePostponedUpdates.
|
||||
consumePostponedUpdates();
|
||||
final int count = mPendingUpdates.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
UpdateOp op = mPendingUpdates.get(i);
|
||||
switch (op.cmd) {
|
||||
case UpdateOp.ADD:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForAdd(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.REMOVE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForRemovingInvisible(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.UPDATE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.markViewHoldersUpdated(op.positionStart, op.itemCount);
|
||||
break;
|
||||
case UpdateOp.MOVE:
|
||||
mCallback.onDispatchSecondPass(op);
|
||||
mCallback.offsetPositionsForMove(op.positionStart, op.itemCount);
|
||||
break;
|
||||
}
|
||||
if (mOnItemProcessedCallback != null) {
|
||||
mOnItemProcessedCallback.run();
|
||||
}
|
||||
}
|
||||
recycleUpdateOpsAndClearList(mPendingUpdates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Queued operation to happen when child views are updated.
|
||||
*/
|
||||
static class UpdateOp {
|
||||
|
||||
static final int ADD = 0;
|
||||
|
||||
static final int REMOVE = 1;
|
||||
|
||||
static final int UPDATE = 2;
|
||||
|
||||
static final int MOVE = 3;
|
||||
|
||||
static final int POOL_SIZE = 30;
|
||||
|
||||
int cmd;
|
||||
|
||||
int positionStart;
|
||||
|
||||
// holds the target position if this is a MOVE
|
||||
int itemCount;
|
||||
|
||||
UpdateOp(int cmd, int positionStart, int itemCount) {
|
||||
this.cmd = cmd;
|
||||
this.positionStart = positionStart;
|
||||
this.itemCount = itemCount;
|
||||
}
|
||||
|
||||
String cmdToString() {
|
||||
switch (cmd) {
|
||||
case ADD:
|
||||
return "add";
|
||||
case REMOVE:
|
||||
return "rm";
|
||||
case UPDATE:
|
||||
return "up";
|
||||
case MOVE:
|
||||
return "mv";
|
||||
}
|
||||
return "??";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + cmdToString() + ",s:" + positionStart + "c:" + itemCount + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateOp op = (UpdateOp) o;
|
||||
|
||||
if (cmd != op.cmd) {
|
||||
return false;
|
||||
}
|
||||
if (cmd == MOVE && Math.abs(itemCount - positionStart) == 1) {
|
||||
// reverse of this is also true
|
||||
if (itemCount == op.positionStart && positionStart == op.itemCount) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (itemCount != op.itemCount) {
|
||||
return false;
|
||||
}
|
||||
if (positionStart != op.positionStart) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = cmd;
|
||||
result = 31 * result + positionStart;
|
||||
result = 31 * result + itemCount;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateOp obtainUpdateOp(int cmd, int positionStart, int itemCount) {
|
||||
UpdateOp op = mUpdateOpPool.acquire();
|
||||
if (op == null) {
|
||||
op = new UpdateOp(cmd, positionStart, itemCount);
|
||||
} else {
|
||||
op.cmd = cmd;
|
||||
op.positionStart = positionStart;
|
||||
op.itemCount = itemCount;
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycleUpdateOp(UpdateOp op) {
|
||||
if (!mDisableRecycler) {
|
||||
mUpdateOpPool.release(op);
|
||||
}
|
||||
}
|
||||
|
||||
void recycleUpdateOpsAndClearList(List<UpdateOp> ops) {
|
||||
final int count = ops.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
recycleUpdateOp(ops.get(i));
|
||||
}
|
||||
ops.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract between AdapterHelper and RecyclerView.
|
||||
*/
|
||||
static interface Callback {
|
||||
|
||||
ViewHolder findViewHolder(int position);
|
||||
|
||||
void offsetPositionsForRemovingInvisible(int positionStart, int itemCount);
|
||||
|
||||
void offsetPositionsForRemovingLaidOutOrNewView(int positionStart, int itemCount);
|
||||
|
||||
void markViewHoldersUpdated(int positionStart, int itemCount);
|
||||
|
||||
void onDispatchFirstPass(UpdateOp updateOp);
|
||||
|
||||
void onDispatchSecondPass(UpdateOp updateOp);
|
||||
|
||||
void offsetPositionsForAdd(int positionStart, int itemCount);
|
||||
|
||||
void offsetPositionsForMove(int from, int to);
|
||||
}
|
||||
}
|
||||
484
app/src/main/java/android/support/v7/widget/ChildHelper.java
Normal file
484
app/src/main/java/android/support/v7/widget/ChildHelper.java
Normal file
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper class to manage children.
|
||||
* <p>
|
||||
* It wraps a RecyclerView and adds ability to hide some children. There are two sets of methods
|
||||
* provided by this class. <b>Regular</b> methods are the ones that replicate ViewGroup methods
|
||||
* like getChildAt, getChildCount etc. These methods ignore hidden children.
|
||||
* <p>
|
||||
* When RecyclerView needs direct access to the view group children, it can call unfiltered
|
||||
* methods like get getUnfilteredChildCount or getUnfilteredChildAt.
|
||||
*/
|
||||
class ChildHelper {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final String TAG = "ChildrenHelper";
|
||||
|
||||
final Callback mCallback;
|
||||
|
||||
final Bucket mBucket;
|
||||
|
||||
final List<View> mHiddenViews;
|
||||
|
||||
ChildHelper(Callback callback) {
|
||||
mCallback = callback;
|
||||
mBucket = new Bucket();
|
||||
mHiddenViews = new ArrayList<View>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a view to the ViewGroup
|
||||
*
|
||||
* @param child View to add.
|
||||
* @param hidden If set to true, this item will be invisible from regular methods.
|
||||
*/
|
||||
void addView(View child, boolean hidden) {
|
||||
addView(child, -1, hidden);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a view to the ViewGroup at an index
|
||||
*
|
||||
* @param child View to add.
|
||||
* @param index Index of the child from the regular perspective (excluding hidden views).
|
||||
* ChildHelper offsets this index to actual ViewGroup index.
|
||||
* @param hidden If set to true, this item will be invisible from regular methods.
|
||||
*/
|
||||
void addView(View child, int index, boolean hidden) {
|
||||
final int offset;
|
||||
if (index < 0) {
|
||||
offset = mCallback.getChildCount();
|
||||
} else {
|
||||
offset = getOffset(index);
|
||||
}
|
||||
mCallback.addView(child, offset);
|
||||
mBucket.insert(offset, hidden);
|
||||
if (hidden) {
|
||||
mHiddenViews.add(child);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addViewAt " + index + ",h:" + hidden + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
private int getOffset(int index) {
|
||||
if (index < 0) {
|
||||
return -1; //anything below 0 won't work as diff will be undefined.
|
||||
}
|
||||
final int limit = mCallback.getChildCount();
|
||||
int offset = index;
|
||||
while (offset < limit) {
|
||||
final int removedBefore = mBucket.countOnesBefore(offset);
|
||||
final int diff = index - (offset - removedBefore);
|
||||
if (diff == 0) {
|
||||
while (mBucket.get(offset)) { // ensure this offset is not hidden
|
||||
offset ++;
|
||||
}
|
||||
return offset;
|
||||
} else {
|
||||
offset += diff;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the provided View from underlying RecyclerView.
|
||||
*
|
||||
* @param view The view to remove.
|
||||
*/
|
||||
void removeView(View view) {
|
||||
int index = mCallback.indexOfChild(view);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
mCallback.removeViewAt(index);
|
||||
if (mBucket.remove(index)) {
|
||||
mHiddenViews.remove(view);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "remove View off:" + index + "," + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the view at the provided index from RecyclerView.
|
||||
*
|
||||
* @param index Index of the child from the regular perspective (excluding hidden views).
|
||||
* ChildHelper offsets this index to actual ViewGroup index.
|
||||
*/
|
||||
void removeViewAt(int index) {
|
||||
final int offset = getOffset(index);
|
||||
final View view = mCallback.getChildAt(offset);
|
||||
if (view == null) {
|
||||
return;
|
||||
}
|
||||
mCallback.removeViewAt(offset);
|
||||
if (mBucket.remove(offset)) {
|
||||
mHiddenViews.remove(view);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "removeViewAt " + index + ", off:" + offset + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the child at provided index.
|
||||
*
|
||||
* @param index Index of the child to return in regular perspective.
|
||||
*/
|
||||
View getChildAt(int index) {
|
||||
final int offset = getOffset(index);
|
||||
return mCallback.getChildAt(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all views from the ViewGroup including the hidden ones.
|
||||
*/
|
||||
void removeAllViewsUnfiltered() {
|
||||
mCallback.removeAllViews();
|
||||
mBucket.reset();
|
||||
mHiddenViews.clear();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "removeAllViewsUnfiltered");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be used to find a disappearing view by position.
|
||||
*
|
||||
* @param position The adapter position of the item.
|
||||
* @param type View type, can be {@link RecyclerView#INVALID_TYPE}.
|
||||
* @return A hidden view with a valid ViewHolder that matches the position and type.
|
||||
*/
|
||||
View findHiddenNonRemovedView(int position, int type) {
|
||||
final int count = mHiddenViews.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
final View view = mHiddenViews.get(i);
|
||||
RecyclerView.ViewHolder holder = mCallback.getChildViewHolder(view);
|
||||
if (holder.getPosition() == position && !holder.isInvalid() &&
|
||||
(type == RecyclerView.INVALID_TYPE || holder.getItemViewType() == type)) {
|
||||
return view;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the provided view to the underlying ViewGroup.
|
||||
*
|
||||
* @param child Child to attach.
|
||||
* @param index Index of the child to attach in regular perspective.
|
||||
* @param layoutParams LayoutParams for the child.
|
||||
* @param hidden If set to true, this item will be invisible to the regular methods.
|
||||
*/
|
||||
void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams,
|
||||
boolean hidden) {
|
||||
final int offset;
|
||||
if (index < 0) {
|
||||
offset = mCallback.getChildCount();
|
||||
} else {
|
||||
offset = getOffset(index);
|
||||
}
|
||||
mCallback.attachViewToParent(child, offset, layoutParams);
|
||||
mBucket.insert(offset, hidden);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "attach view to parent index:" + index + ",off:" + offset + "," +
|
||||
"h:" + hidden + ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of children that are not hidden.
|
||||
*
|
||||
* @return Number of children that are not hidden.
|
||||
* @see #getChildAt(int)
|
||||
*/
|
||||
int getChildCount() {
|
||||
return mCallback.getChildCount() - mHiddenViews.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of children.
|
||||
*
|
||||
* @return The total number of children including the hidden views.
|
||||
* @see #getUnfilteredChildAt(int)
|
||||
*/
|
||||
int getUnfilteredChildCount() {
|
||||
return mCallback.getChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a child by ViewGroup offset. ChildHelper won't offset this index.
|
||||
*
|
||||
* @param index ViewGroup index of the child to return.
|
||||
* @return The view in the provided index.
|
||||
*/
|
||||
View getUnfilteredChildAt(int index) {
|
||||
return mCallback.getChildAt(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detaches the view at the provided index.
|
||||
*
|
||||
* @param index Index of the child to return in regular perspective.
|
||||
*/
|
||||
void detachViewFromParent(int index) {
|
||||
final int offset = getOffset(index);
|
||||
mCallback.detachViewFromParent(offset);
|
||||
mBucket.remove(offset);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "detach view from parent " + index + ", off:" + offset);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the child in regular perspective.
|
||||
*
|
||||
* @param child The child whose index will be returned.
|
||||
* @return The regular perspective index of the child or -1 if it does not exists.
|
||||
*/
|
||||
int indexOfChild(View child) {
|
||||
final int index = mCallback.indexOfChild(child);
|
||||
if (index == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (mBucket.get(index)) {
|
||||
if (DEBUG) {
|
||||
throw new IllegalArgumentException("cannot get index of a hidden child");
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
// reverse the index
|
||||
return index - mBucket.countOnesBefore(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a View is visible to LayoutManager or not.
|
||||
*
|
||||
* @param view The child view to check. Should be a child of the Callback.
|
||||
* @return True if the View is not visible to LayoutManager
|
||||
*/
|
||||
boolean isHidden(View view) {
|
||||
return mHiddenViews.contains(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a child view as hidden.
|
||||
*
|
||||
* @param view The view to hide.
|
||||
*/
|
||||
void hide(View view) {
|
||||
final int offset = mCallback.indexOfChild(view);
|
||||
if (offset < 0) {
|
||||
throw new IllegalArgumentException("view is not a child, cannot hide " + view);
|
||||
}
|
||||
if (DEBUG && mBucket.get(offset)) {
|
||||
throw new RuntimeException("trying to hide same view twice, how come ? " + view);
|
||||
}
|
||||
mBucket.set(offset);
|
||||
mHiddenViews.add(view);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "hiding child " + view + " at offset " + offset+ ", " + this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return mBucket.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a view from the ViewGroup if it is hidden.
|
||||
*
|
||||
* @param view The view to remove.
|
||||
* @return True if the View is found and it is hidden. False otherwise.
|
||||
*/
|
||||
boolean removeViewIfHidden(View view) {
|
||||
final int index = mCallback.indexOfChild(view);
|
||||
if (index == -1) {
|
||||
if (mHiddenViews.remove(view) && DEBUG) {
|
||||
throw new IllegalStateException("view is in hidden list but not in view group");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (mBucket.get(index)) {
|
||||
mBucket.remove(index);
|
||||
mCallback.removeViewAt(index);
|
||||
if (!mHiddenViews.remove(view) && DEBUG) {
|
||||
throw new IllegalStateException(
|
||||
"removed a hidden view but it is not in hidden views list");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitset implementation that provides methods to offset indices.
|
||||
*/
|
||||
static class Bucket {
|
||||
|
||||
final static int BITS_PER_WORD = Long.SIZE;
|
||||
|
||||
final static long LAST_BIT = 1L << (Long.SIZE - 1);
|
||||
|
||||
long mData = 0;
|
||||
|
||||
Bucket next;
|
||||
|
||||
void set(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
next.set(index - BITS_PER_WORD);
|
||||
} else {
|
||||
mData |= 1L << index;
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureNext() {
|
||||
if (next == null) {
|
||||
next = new Bucket();
|
||||
}
|
||||
}
|
||||
|
||||
void clear(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
if (next != null) {
|
||||
next.clear(index - BITS_PER_WORD);
|
||||
}
|
||||
} else {
|
||||
mData &= ~(1L << index);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean get(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
return next.get(index - BITS_PER_WORD);
|
||||
} else {
|
||||
return (mData & (1L << index)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
mData = 0;
|
||||
if (next != null) {
|
||||
next.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void insert(int index, boolean value) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
next.insert(index - BITS_PER_WORD, value);
|
||||
} else {
|
||||
final boolean lastBit = (mData & LAST_BIT) != 0;
|
||||
long mask = (1L << index) - 1;
|
||||
final long before = mData & mask;
|
||||
final long after = ((mData & ~mask)) << 1;
|
||||
mData = before | after;
|
||||
if (value) {
|
||||
set(index);
|
||||
} else {
|
||||
clear(index);
|
||||
}
|
||||
if (lastBit || next != null) {
|
||||
ensureNext();
|
||||
next.insert(0, lastBit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean remove(int index) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
ensureNext();
|
||||
return next.remove(index - BITS_PER_WORD);
|
||||
} else {
|
||||
long mask = (1L << index);
|
||||
final boolean value = (mData & mask) != 0;
|
||||
mData &= ~mask;
|
||||
mask = mask - 1;
|
||||
final long before = mData & mask;
|
||||
// cannot use >> because it adds one.
|
||||
final long after = Long.rotateRight(mData & ~mask, 1);
|
||||
mData = before | after;
|
||||
if (next != null) {
|
||||
if (next.get(0)) {
|
||||
set(BITS_PER_WORD - 1);
|
||||
}
|
||||
next.remove(0);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
int countOnesBefore(int index) {
|
||||
if (next == null) {
|
||||
if (index >= BITS_PER_WORD) {
|
||||
return Long.bitCount(mData);
|
||||
}
|
||||
return Long.bitCount(mData & ((1L << index) - 1));
|
||||
}
|
||||
if (index < BITS_PER_WORD) {
|
||||
return Long.bitCount(mData & ((1L << index) - 1));
|
||||
} else {
|
||||
return next.countOnesBefore(index - BITS_PER_WORD) + Long.bitCount(mData);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return next == null ? Long.toBinaryString(mData)
|
||||
: next.toString() + "xx" + Long.toBinaryString(mData);
|
||||
}
|
||||
}
|
||||
|
||||
static interface Callback {
|
||||
|
||||
int getChildCount();
|
||||
|
||||
void addView(View child, int index);
|
||||
|
||||
int indexOfChild(View view);
|
||||
|
||||
void removeViewAt(int index);
|
||||
|
||||
View getChildAt(int offset);
|
||||
|
||||
void removeAllViews();
|
||||
|
||||
RecyclerView.ViewHolder getChildViewHolder(View view);
|
||||
|
||||
void attachViewToParent(View child, int index, ViewGroup.LayoutParams layoutParams);
|
||||
|
||||
void detachViewFromParent(int offset);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,628 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.support.v7.widget;
|
||||
|
||||
import android.support.v4.view.ViewCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorCompat;
|
||||
import android.support.v4.view.ViewPropertyAnimatorListener;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.View;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This implementation of {@link RecyclerView.ItemAnimator} provides basic
|
||||
* animations on remove, add, and move events that happen to the items in
|
||||
* a RecyclerView. RecyclerView uses a DefaultItemAnimator by default.
|
||||
*
|
||||
* @see RecyclerView#setItemAnimator(RecyclerView.ItemAnimator)
|
||||
*/
|
||||
public class DefaultItemAnimator extends RecyclerView.ItemAnimator {
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mPendingAdditions = new ArrayList<ViewHolder>();
|
||||
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<MoveInfo>();
|
||||
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<ChangeInfo>();
|
||||
|
||||
private ArrayList<ArrayList<ViewHolder>> mAdditionsList =
|
||||
new ArrayList<ArrayList<ViewHolder>>();
|
||||
private ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<ArrayList<MoveInfo>>();
|
||||
private ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<ArrayList<ChangeInfo>>();
|
||||
|
||||
private ArrayList<ViewHolder> mAddAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mMoveAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<ViewHolder>();
|
||||
private ArrayList<ViewHolder> mChangeAnimations = new ArrayList<ViewHolder>();
|
||||
|
||||
private static class MoveInfo {
|
||||
public ViewHolder holder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
|
||||
private MoveInfo(ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
this.holder = holder;
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ChangeInfo {
|
||||
public ViewHolder oldHolder, newHolder;
|
||||
public int fromX, fromY, toX, toY;
|
||||
private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder) {
|
||||
this.oldHolder = oldHolder;
|
||||
this.newHolder = newHolder;
|
||||
}
|
||||
|
||||
private ChangeInfo(ViewHolder oldHolder, ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
this(oldHolder, newHolder);
|
||||
this.fromX = fromX;
|
||||
this.fromY = fromY;
|
||||
this.toX = toX;
|
||||
this.toY = toY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChangeInfo{" +
|
||||
"oldHolder=" + oldHolder +
|
||||
", newHolder=" + newHolder +
|
||||
", fromX=" + fromX +
|
||||
", fromY=" + fromY +
|
||||
", toX=" + toX +
|
||||
", toY=" + toY +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runPendingAnimations() {
|
||||
boolean removalsPending = !mPendingRemovals.isEmpty();
|
||||
boolean movesPending = !mPendingMoves.isEmpty();
|
||||
boolean changesPending = !mPendingChanges.isEmpty();
|
||||
boolean additionsPending = !mPendingAdditions.isEmpty();
|
||||
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
|
||||
// nothing to animate
|
||||
return;
|
||||
}
|
||||
// First, remove stuff
|
||||
for (ViewHolder holder : mPendingRemovals) {
|
||||
animateRemoveImpl(holder);
|
||||
}
|
||||
mPendingRemovals.clear();
|
||||
// Next, move stuff
|
||||
if (movesPending) {
|
||||
final ArrayList<MoveInfo> moves = new ArrayList<MoveInfo>();
|
||||
moves.addAll(mPendingMoves);
|
||||
mMovesList.add(moves);
|
||||
mPendingMoves.clear();
|
||||
Runnable mover = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (MoveInfo moveInfo : moves) {
|
||||
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
|
||||
moveInfo.toX, moveInfo.toY);
|
||||
}
|
||||
moves.clear();
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
};
|
||||
if (removalsPending) {
|
||||
View view = moves.get(0).holder.itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
|
||||
} else {
|
||||
mover.run();
|
||||
}
|
||||
}
|
||||
// Next, change stuff, to run in parallel with move animations
|
||||
if (changesPending) {
|
||||
final ArrayList<ChangeInfo> changes = new ArrayList<ChangeInfo>();
|
||||
changes.addAll(mPendingChanges);
|
||||
mChangesList.add(changes);
|
||||
mPendingChanges.clear();
|
||||
Runnable changer = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ChangeInfo change : changes) {
|
||||
animateChangeImpl(change);
|
||||
}
|
||||
changes.clear();
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
};
|
||||
if (removalsPending) {
|
||||
ViewHolder holder = changes.get(0).oldHolder;
|
||||
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
|
||||
} else {
|
||||
changer.run();
|
||||
}
|
||||
}
|
||||
// Next, add stuff
|
||||
if (additionsPending) {
|
||||
final ArrayList<ViewHolder> additions = new ArrayList<ViewHolder>();
|
||||
additions.addAll(mPendingAdditions);
|
||||
mAdditionsList.add(additions);
|
||||
mPendingAdditions.clear();
|
||||
Runnable adder = new Runnable() {
|
||||
public void run() {
|
||||
for (ViewHolder holder : additions) {
|
||||
animateAddImpl(holder);
|
||||
}
|
||||
additions.clear();
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
};
|
||||
if (removalsPending || movesPending || changesPending) {
|
||||
long removeDuration = removalsPending ? getRemoveDuration() : 0;
|
||||
long moveDuration = movesPending ? getMoveDuration() : 0;
|
||||
long changeDuration = changesPending ? getChangeDuration() : 0;
|
||||
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
|
||||
View view = additions.get(0).itemView;
|
||||
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
|
||||
} else {
|
||||
adder.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateRemove(final ViewHolder holder) {
|
||||
endAnimation(holder);
|
||||
mPendingRemovals.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateRemoveImpl(final ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.setDuration(getRemoveDuration())
|
||||
.alpha(0).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchRemoveStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchRemoveFinished(holder);
|
||||
mRemoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
mRemoveAnimations.add(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateAdd(final ViewHolder holder) {
|
||||
endAnimation(holder);
|
||||
ViewCompat.setAlpha(holder.itemView, 0);
|
||||
mPendingAdditions.add(holder);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateAddImpl(final ViewHolder holder) {
|
||||
final View view = holder.itemView;
|
||||
mAddAnimations.add(holder);
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.alpha(1).setDuration(getAddDuration()).
|
||||
setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchAddStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
dispatchAddFinished(holder);
|
||||
mAddAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateMove(final ViewHolder holder, int fromX, int fromY,
|
||||
int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
fromX += ViewCompat.getTranslationX(holder.itemView);
|
||||
fromY += ViewCompat.getTranslationY(holder.itemView);
|
||||
endAnimation(holder);
|
||||
int deltaX = toX - fromX;
|
||||
int deltaY = toY - fromY;
|
||||
if (deltaX == 0 && deltaY == 0) {
|
||||
dispatchMoveFinished(holder);
|
||||
return false;
|
||||
}
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.setTranslationX(view, -deltaX);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.setTranslationY(view, -deltaY);
|
||||
}
|
||||
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateMoveImpl(final ViewHolder holder, int fromX, int fromY, int toX, int toY) {
|
||||
final View view = holder.itemView;
|
||||
final int deltaX = toX - fromX;
|
||||
final int deltaY = toY - fromY;
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.animate(view).translationX(0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.animate(view).translationY(0);
|
||||
}
|
||||
// TODO: make EndActions end listeners instead, since end actions aren't called when
|
||||
// vpas are canceled (and can't end them. why?)
|
||||
// need listener functionality in VPACompat for this. Ick.
|
||||
mMoveAnimations.add(holder);
|
||||
final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
|
||||
animation.setDuration(getMoveDuration()).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchMoveStarting(holder);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {
|
||||
if (deltaX != 0) {
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
}
|
||||
if (deltaY != 0) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
animation.setListener(null);
|
||||
dispatchMoveFinished(holder);
|
||||
mMoveAnimations.remove(holder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean animateChange(ViewHolder oldHolder, ViewHolder newHolder,
|
||||
int fromX, int fromY, int toX, int toY) {
|
||||
final float prevTranslationX = ViewCompat.getTranslationX(oldHolder.itemView);
|
||||
final float prevTranslationY = ViewCompat.getTranslationY(oldHolder.itemView);
|
||||
final float prevAlpha = ViewCompat.getAlpha(oldHolder.itemView);
|
||||
endAnimation(oldHolder);
|
||||
int deltaX = (int) (toX - fromX - prevTranslationX);
|
||||
int deltaY = (int) (toY - fromY - prevTranslationY);
|
||||
// recover prev translation state after ending animation
|
||||
ViewCompat.setTranslationX(oldHolder.itemView, prevTranslationX);
|
||||
ViewCompat.setTranslationY(oldHolder.itemView, prevTranslationY);
|
||||
ViewCompat.setAlpha(oldHolder.itemView, prevAlpha);
|
||||
if (newHolder != null && newHolder.itemView != null) {
|
||||
// carry over translation values
|
||||
endAnimation(newHolder);
|
||||
ViewCompat.setTranslationX(newHolder.itemView, -deltaX);
|
||||
ViewCompat.setTranslationY(newHolder.itemView, -deltaY);
|
||||
ViewCompat.setAlpha(newHolder.itemView, 0);
|
||||
}
|
||||
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void animateChangeImpl(final ChangeInfo changeInfo) {
|
||||
final ViewHolder holder = changeInfo.oldHolder;
|
||||
final View view = holder.itemView;
|
||||
final ViewHolder newHolder = changeInfo.newHolder;
|
||||
final View newView = newHolder != null ? newHolder.itemView : null;
|
||||
mChangeAnimations.add(changeInfo.oldHolder);
|
||||
|
||||
final ViewPropertyAnimatorCompat oldViewAnim = ViewCompat.animate(view).setDuration(
|
||||
getChangeDuration());
|
||||
oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
|
||||
oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
|
||||
oldViewAnim.alpha(0).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchChangeStarting(changeInfo.oldHolder, true);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
oldViewAnim.setListener(null);
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
dispatchChangeFinished(changeInfo.oldHolder, true);
|
||||
mChangeAnimations.remove(changeInfo.oldHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
if (newView != null) {
|
||||
mChangeAnimations.add(changeInfo.newHolder);
|
||||
final ViewPropertyAnimatorCompat newViewAnimation = ViewCompat.animate(newView);
|
||||
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).
|
||||
alpha(1).setListener(new VpaListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {
|
||||
dispatchChangeStarting(changeInfo.newHolder, false);
|
||||
}
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {
|
||||
newViewAnimation.setListener(null);
|
||||
ViewCompat.setAlpha(newView, 1);
|
||||
ViewCompat.setTranslationX(newView, 0);
|
||||
ViewCompat.setTranslationY(newView, 0);
|
||||
dispatchChangeFinished(changeInfo.newHolder, false);
|
||||
mChangeAnimations.remove(changeInfo.newHolder);
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimation(List<ChangeInfo> infoList, ViewHolder item) {
|
||||
for (int i = infoList.size() - 1; i >= 0; i--) {
|
||||
ChangeInfo changeInfo = infoList.get(i);
|
||||
if (endChangeAnimationIfNecessary(changeInfo, item)) {
|
||||
if (changeInfo.oldHolder == null && changeInfo.newHolder == null) {
|
||||
infoList.remove(changeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void endChangeAnimationIfNecessary(ChangeInfo changeInfo) {
|
||||
if (changeInfo.oldHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.oldHolder);
|
||||
}
|
||||
if (changeInfo.newHolder != null) {
|
||||
endChangeAnimationIfNecessary(changeInfo, changeInfo.newHolder);
|
||||
}
|
||||
}
|
||||
private boolean endChangeAnimationIfNecessary(ChangeInfo changeInfo, ViewHolder item) {
|
||||
boolean oldItem = false;
|
||||
if (changeInfo.newHolder == item) {
|
||||
changeInfo.newHolder = null;
|
||||
} else if (changeInfo.oldHolder == item) {
|
||||
changeInfo.oldHolder = null;
|
||||
oldItem = true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
ViewCompat.setAlpha(item.itemView, 1);
|
||||
ViewCompat.setTranslationX(item.itemView, 0);
|
||||
ViewCompat.setTranslationY(item.itemView, 0);
|
||||
dispatchChangeFinished(item, oldItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimation(ViewHolder item) {
|
||||
final View view = item.itemView;
|
||||
// this will trigger end callback which should set properties to their target values.
|
||||
ViewCompat.animate(view).cancel();
|
||||
// TODO if some other animations are chained to end, how do we cancel them as well?
|
||||
for (int i = mPendingMoves.size() - 1; i >= 0; i--) {
|
||||
MoveInfo moveInfo = mPendingMoves.get(i);
|
||||
if (moveInfo.holder == item) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item);
|
||||
mPendingMoves.remove(item);
|
||||
}
|
||||
}
|
||||
endChangeAnimation(mPendingChanges, item);
|
||||
if (mPendingRemovals.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchRemoveFinished(item);
|
||||
}
|
||||
if (mPendingAdditions.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
}
|
||||
|
||||
for (int i = mChangesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
endChangeAnimation(changes, item);
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
}
|
||||
for (int i = mMovesList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
for (int j = moves.size() - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
if (moveInfo.holder == item) {
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = mAdditionsList.size() - 1; i >= 0; i--) {
|
||||
ArrayList<ViewHolder> additions = mAdditionsList.get(i);
|
||||
if (additions.remove(item)) {
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animations should be ended by the cancel above.
|
||||
if (mRemoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mRemoveAnimations list");
|
||||
}
|
||||
|
||||
if (mAddAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mAddAnimations list");
|
||||
}
|
||||
|
||||
if (mChangeAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mChangeAnimations list");
|
||||
}
|
||||
|
||||
if (mMoveAnimations.remove(item) && DEBUG) {
|
||||
throw new IllegalStateException("after animation is cancelled, item should not be in "
|
||||
+ "mMoveAnimations list");
|
||||
}
|
||||
dispatchFinishedWhenDone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return (!mPendingAdditions.isEmpty() ||
|
||||
!mPendingChanges.isEmpty() ||
|
||||
!mPendingMoves.isEmpty() ||
|
||||
!mPendingRemovals.isEmpty() ||
|
||||
!mMoveAnimations.isEmpty() ||
|
||||
!mRemoveAnimations.isEmpty() ||
|
||||
!mAddAnimations.isEmpty() ||
|
||||
!mChangeAnimations.isEmpty() ||
|
||||
!mMovesList.isEmpty() ||
|
||||
!mAdditionsList.isEmpty() ||
|
||||
!mChangesList.isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the state of currently pending and running animations. If there are none
|
||||
* pending/running, call {@link #dispatchAnimationsFinished()} to notify any
|
||||
* listeners.
|
||||
*/
|
||||
private void dispatchFinishedWhenDone() {
|
||||
if (!isRunning()) {
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endAnimations() {
|
||||
int count = mPendingMoves.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
MoveInfo item = mPendingMoves.get(i);
|
||||
View view = item.holder.itemView;
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(item.holder);
|
||||
mPendingMoves.remove(i);
|
||||
}
|
||||
count = mPendingRemovals.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
ViewHolder item = mPendingRemovals.get(i);
|
||||
dispatchRemoveFinished(item);
|
||||
mPendingRemovals.remove(i);
|
||||
}
|
||||
count = mPendingAdditions.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
ViewHolder item = mPendingAdditions.get(i);
|
||||
View view = item.itemView;
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
mPendingAdditions.remove(i);
|
||||
}
|
||||
count = mPendingChanges.size();
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
endChangeAnimationIfNecessary(mPendingChanges.get(i));
|
||||
}
|
||||
mPendingChanges.clear();
|
||||
if (!isRunning()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int listCount = mMovesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<MoveInfo> moves = mMovesList.get(i);
|
||||
count = moves.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
MoveInfo moveInfo = moves.get(j);
|
||||
ViewHolder item = moveInfo.holder;
|
||||
View view = item.itemView;
|
||||
ViewCompat.setTranslationY(view, 0);
|
||||
ViewCompat.setTranslationX(view, 0);
|
||||
dispatchMoveFinished(moveInfo.holder);
|
||||
moves.remove(j);
|
||||
if (moves.isEmpty()) {
|
||||
mMovesList.remove(moves);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mAdditionsList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<ViewHolder> additions = mAdditionsList.get(i);
|
||||
count = additions.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
ViewHolder item = additions.get(j);
|
||||
View view = item.itemView;
|
||||
ViewCompat.setAlpha(view, 1);
|
||||
dispatchAddFinished(item);
|
||||
additions.remove(j);
|
||||
if (additions.isEmpty()) {
|
||||
mAdditionsList.remove(additions);
|
||||
}
|
||||
}
|
||||
}
|
||||
listCount = mChangesList.size();
|
||||
for (int i = listCount - 1; i >= 0; i--) {
|
||||
ArrayList<ChangeInfo> changes = mChangesList.get(i);
|
||||
count = changes.size();
|
||||
for (int j = count - 1; j >= 0; j--) {
|
||||
endChangeAnimationIfNecessary(changes.get(j));
|
||||
if (changes.isEmpty()) {
|
||||
mChangesList.remove(changes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelAll(mRemoveAnimations);
|
||||
cancelAll(mMoveAnimations);
|
||||
cancelAll(mAddAnimations);
|
||||
cancelAll(mChangeAnimations);
|
||||
|
||||
dispatchAnimationsFinished();
|
||||
}
|
||||
|
||||
void cancelAll(List<ViewHolder> viewHolders) {
|
||||
for (int i = viewHolders.size() - 1; i >= 0; i--) {
|
||||
ViewCompat.animate(viewHolders.get(i).itemView).cancel();
|
||||
}
|
||||
}
|
||||
|
||||
private static class VpaListenerAdapter implements ViewPropertyAnimatorListener {
|
||||
@Override
|
||||
public void onAnimationStart(View view) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(View view) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(View view) {}
|
||||
};
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user