Compare commits

..

3 Commits

Author SHA1 Message Date
f3cc84bcf3 Update modules.xml 2016-08-01 11:11:28 +08:00
4e89e623c6 Update .gitignore 2016-08-01 11:09:02 +08:00
3d07b0b025 . 2016-08-01 10:31:11 +08:00
6423 changed files with 87524 additions and 507240 deletions

View File

@ -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
View File

@ -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

View File

@ -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
View File

@ -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
View File

@ -0,0 +1 @@
GH-ASSISTv1.45

22
.idea/compiler.xml generated Normal file
View 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
View File

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

6
.idea/encodings.xml generated Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -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修改

View File

@ -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

View File

@ -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 新配置项时请检查可用性(如语法等)

View File

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
app/libs/gson-2.3.1.jar Normal file

Binary file not shown.

BIN
app/libs/mid-sdk-2.3.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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
View 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 *;
#}

View File

@ -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;
}

View File

@ -1,4 +0,0 @@
storeFile=gh.keystore
storePassword=20150318
keyAlias=gh.keystore
keyPassword=20150318

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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)
})
}
}
}

View File

@ -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"
}
}

View File

@ -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 })
}
}
}
}

View File

@ -1,5 +0,0 @@
package com.gh.vspace.installexternalgames;
public class Constants {
public static final String TAG = "从SD卡安装";
}

View File

@ -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)
}
}
}
}

View File

@ -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,
)

View File

@ -1,6 +0,0 @@
package com.gh.vspace.installexternalgames
data class ExternalGameUiState(
val externalGameEntity: ExternalGameEntity,
val isInstalled: Boolean
)

View File

@ -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
}

View File

@ -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())
}
}
}

View File

@ -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)
}
}

View File

@ -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()
}
}

View File

@ -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)
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="install_game_from_external" type="id" />
</resources>

View File

@ -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>

View File

@ -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>

View File

@ -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()
}
}
}

View File

@ -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"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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>

View File

@ -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);
}
}
});
});

View File

@ -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":[
]
}
}
]
}

View File

@ -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>

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

View File

@ -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":[]}

View File

@ -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

View File

@ -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":[]}

View File

@ -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":[]}

View File

@ -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

View File

@ -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":[]}

View File

@ -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

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 +'"/> &nbsp;';
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);
}

View File

@ -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

File diff suppressed because one or more lines are too long

View 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);
}
}

View 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);
}
}

View File

@ -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