diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..6acf686
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,568 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 120
+tab_width = 2
+ij_continuation_indent_size = 2
+ij_formatter_off_tag = @fmt:off
+ij_formatter_on_tag = @fmt:on
+ij_formatter_tags_enabled = false
+ij_smart_tabs = true
+ij_visual_guides = none
+ij_wrap_on_typing = false
+
+[*.java]
+ij_java_align_consecutive_assignments = false
+ij_java_align_consecutive_variable_declarations = false
+ij_java_align_group_field_declarations = false
+ij_java_align_multiline_annotation_parameters = false
+ij_java_align_multiline_array_initializer_expression = false
+ij_java_align_multiline_assignment = false
+ij_java_align_multiline_binary_operation = false
+ij_java_align_multiline_chained_methods = false
+ij_java_align_multiline_extends_list = false
+ij_java_align_multiline_for = true
+ij_java_align_multiline_method_parentheses = false
+ij_java_align_multiline_parameters = true
+ij_java_align_multiline_parameters_in_calls = false
+ij_java_align_multiline_parenthesized_expression = false
+ij_java_align_multiline_records = true
+ij_java_align_multiline_resources = true
+ij_java_align_multiline_ternary_operation = false
+ij_java_align_multiline_text_blocks = false
+ij_java_align_multiline_throws_list = false
+ij_java_align_subsequent_simple_methods = false
+ij_java_align_throws_keyword = false
+ij_java_annotation_parameter_wrap = off
+ij_java_array_initializer_new_line_after_left_brace = false
+ij_java_array_initializer_right_brace_on_new_line = false
+ij_java_array_initializer_wrap = off
+ij_java_assert_statement_colon_on_next_line = false
+ij_java_assert_statement_wrap = off
+ij_java_assignment_wrap = off
+ij_java_binary_operation_sign_on_next_line = false
+ij_java_binary_operation_wrap = off
+ij_java_blank_lines_after_anonymous_class_header = 0
+ij_java_blank_lines_after_class_header = 0
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_after_package = 1
+ij_java_blank_lines_around_class = 1
+ij_java_blank_lines_around_field = 0
+ij_java_blank_lines_around_field_in_interface = 0
+ij_java_blank_lines_around_initializer = 1
+ij_java_blank_lines_around_method = 1
+ij_java_blank_lines_around_method_in_interface = 0
+ij_java_blank_lines_before_class_end = 0
+ij_java_blank_lines_before_imports = 1
+ij_java_blank_lines_before_method_body = 0
+ij_java_blank_lines_before_package = 0
+ij_java_block_brace_style = end_of_line
+ij_java_block_comment_at_first_column = true
+ij_java_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 = 5
+ij_java_class_names_in_javadoc = 1
+ij_java_do_not_indent_top_level_class_members = false
+ij_java_do_not_wrap_after_single_annotation = false
+ij_java_do_while_brace_force = never
+ij_java_doc_add_blank_line_after_description = true
+ij_java_doc_add_blank_line_after_param_comments = false
+ij_java_doc_add_blank_line_after_return = false
+ij_java_doc_add_p_tag_on_empty_lines = true
+ij_java_doc_align_exception_comments = true
+ij_java_doc_align_param_comments = true
+ij_java_doc_do_not_wrap_if_one_line = true
+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 = *,|,javax.**,java.**,|,$*
+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_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 = true
+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 = true
+ij_java_line_comment_at_first_column = false
+ij_java_method_annotation_wrap = normal
+ij_java_method_brace_style = end_of_line
+ij_java_method_call_chain_wrap = off
+ij_java_method_parameters_new_line_after_left_paren = false
+ij_java_method_parameters_right_paren_on_new_line = false
+ij_java_method_parameters_wrap = off
+ij_java_modifier_list_wrap = false
+ij_java_names_count_to_use_import_on_demand = 3
+ij_java_new_line_after_lparen_in_record_header = false
+ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
+ij_java_parameter_annotation_wrap = off
+ij_java_parentheses_expression_new_line_after_left_paren = false
+ij_java_parentheses_expression_right_paren_on_new_line = false
+ij_java_place_assignment_sign_on_next_line = false
+ij_java_prefer_longer_names = true
+ij_java_prefer_parameters_wrap = false
+ij_java_record_components_wrap = normal
+ij_java_repeat_synchronized = true
+ij_java_replace_instanceof_and_cast = false
+ij_java_replace_null_check = true
+ij_java_replace_sum_lambda_with_method_ref = true
+ij_java_resource_list_new_line_after_left_paren = false
+ij_java_resource_list_right_paren_on_new_line = false
+ij_java_resource_list_wrap = off
+ij_java_rparen_on_new_line_in_record_header = false
+ij_java_space_after_closing_angle_bracket_in_type_argument = false
+ij_java_space_after_colon = true
+ij_java_space_after_comma = true
+ij_java_space_after_comma_in_type_arguments = true
+ij_java_space_after_for_semicolon = true
+ij_java_space_after_quest = true
+ij_java_space_after_type_cast = true
+ij_java_space_before_annotation_array_initializer_left_brace = false
+ij_java_space_before_annotation_parameter_list = false
+ij_java_space_before_array_initializer_left_brace = false
+ij_java_space_before_catch_keyword = true
+ij_java_space_before_catch_left_brace = true
+ij_java_space_before_catch_parentheses = true
+ij_java_space_before_class_left_brace = true
+ij_java_space_before_colon = true
+ij_java_space_before_colon_in_foreach = true
+ij_java_space_before_comma = false
+ij_java_space_before_do_left_brace = true
+ij_java_space_before_else_keyword = true
+ij_java_space_before_else_left_brace = true
+ij_java_space_before_finally_keyword = true
+ij_java_space_before_finally_left_brace = true
+ij_java_space_before_for_left_brace = true
+ij_java_space_before_for_parentheses = true
+ij_java_space_before_for_semicolon = false
+ij_java_space_before_if_left_brace = true
+ij_java_space_before_if_parentheses = true
+ij_java_space_before_method_call_parentheses = false
+ij_java_space_before_method_left_brace = true
+ij_java_space_before_method_parentheses = false
+ij_java_space_before_opening_angle_bracket_in_type_parameter = false
+ij_java_space_before_quest = true
+ij_java_space_before_switch_left_brace = true
+ij_java_space_before_switch_parentheses = true
+ij_java_space_before_synchronized_left_brace = true
+ij_java_space_before_synchronized_parentheses = true
+ij_java_space_before_try_left_brace = true
+ij_java_space_before_try_parentheses = true
+ij_java_space_before_type_parameter_list = false
+ij_java_space_before_while_keyword = true
+ij_java_space_before_while_left_brace = true
+ij_java_space_before_while_parentheses = true
+ij_java_space_inside_one_line_enum_braces = false
+ij_java_space_within_empty_array_initializer_braces = false
+ij_java_space_within_empty_method_call_parentheses = false
+ij_java_space_within_empty_method_parentheses = false
+ij_java_spaces_around_additive_operators = true
+ij_java_spaces_around_assignment_operators = true
+ij_java_spaces_around_bitwise_operators = true
+ij_java_spaces_around_equality_operators = true
+ij_java_spaces_around_lambda_arrow = true
+ij_java_spaces_around_logical_operators = true
+ij_java_spaces_around_method_ref_dbl_colon = false
+ij_java_spaces_around_multiplicative_operators = true
+ij_java_spaces_around_relational_operators = true
+ij_java_spaces_around_shift_operators = true
+ij_java_spaces_around_type_bounds_in_type_parameters = true
+ij_java_spaces_around_unary_operator = false
+ij_java_spaces_within_angle_brackets = false
+ij_java_spaces_within_annotation_parentheses = false
+ij_java_spaces_within_array_initializer_braces = false
+ij_java_spaces_within_braces = false
+ij_java_spaces_within_brackets = false
+ij_java_spaces_within_cast_parentheses = false
+ij_java_spaces_within_catch_parentheses = false
+ij_java_spaces_within_for_parentheses = false
+ij_java_spaces_within_if_parentheses = false
+ij_java_spaces_within_method_call_parentheses = false
+ij_java_spaces_within_method_parentheses = false
+ij_java_spaces_within_parentheses = false
+ij_java_spaces_within_record_header = false
+ij_java_spaces_within_switch_parentheses = false
+ij_java_spaces_within_synchronized_parentheses = false
+ij_java_spaces_within_try_parentheses = false
+ij_java_spaces_within_while_parentheses = false
+ij_java_special_else_if_treatment = true
+ij_java_subclass_name_suffix = Impl
+ij_java_ternary_operation_signs_on_next_line = false
+ij_java_ternary_operation_wrap = off
+ij_java_test_name_suffix = Test
+ij_java_throws_keyword_wrap = off
+ij_java_throws_list_wrap = off
+ij_java_use_external_annotations = false
+ij_java_use_fq_class_names = false
+ij_java_use_relative_indents = false
+ij_java_use_single_class_imports = true
+ij_java_variable_annotation_wrap = off
+ij_java_visibility = public
+ij_java_while_brace_force = never
+ij_java_while_on_new_line = false
+ij_java_wrap_comments = false
+ij_java_wrap_first_method_in_call_chain = false
+ij_java_wrap_long_lines = false
+
+[*.properties]
+ij_properties_align_group_field_declarations = false
+ij_properties_keep_blank_lines = false
+ij_properties_key_value_delimiter = equals
+ij_properties_spaces_around_key_value_delimiter = false
+
+[*.proto]
+ij_proto_keep_indents_on_empty_lines = false
+
+[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.jspx,*.pom,*.rng,*.tagx,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
+ij_xml_align_attributes = true
+ij_xml_align_text = false
+ij_xml_attribute_wrap = normal
+ij_xml_block_comment_at_first_column = true
+ij_xml_keep_blank_lines = 1
+ij_xml_keep_indents_on_empty_lines = false
+ij_xml_keep_line_breaks = true
+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 = false
+ij_xml_text_wrap = normal
+
+[{*.gant,*.gradle,*.groovy,*.gy}]
+ij_groovy_align_group_field_declarations = false
+ij_groovy_align_multiline_array_initializer_expression = false
+ij_groovy_align_multiline_assignment = false
+ij_groovy_align_multiline_binary_operation = false
+ij_groovy_align_multiline_chained_methods = false
+ij_groovy_align_multiline_extends_list = false
+ij_groovy_align_multiline_for = true
+ij_groovy_align_multiline_list_or_map = true
+ij_groovy_align_multiline_method_parentheses = false
+ij_groovy_align_multiline_parameters = true
+ij_groovy_align_multiline_parameters_in_calls = false
+ij_groovy_align_multiline_resources = true
+ij_groovy_align_multiline_ternary_operation = false
+ij_groovy_align_multiline_throws_list = false
+ij_groovy_align_named_args_in_map = true
+ij_groovy_align_throws_keyword = false
+ij_groovy_array_initializer_new_line_after_left_brace = false
+ij_groovy_array_initializer_right_brace_on_new_line = false
+ij_groovy_array_initializer_wrap = off
+ij_groovy_assert_statement_wrap = off
+ij_groovy_assignment_wrap = off
+ij_groovy_binary_operation_wrap = off
+ij_groovy_blank_lines_after_class_header = 0
+ij_groovy_blank_lines_after_imports = 1
+ij_groovy_blank_lines_after_package = 1
+ij_groovy_blank_lines_around_class = 1
+ij_groovy_blank_lines_around_field = 0
+ij_groovy_blank_lines_around_field_in_interface = 0
+ij_groovy_blank_lines_around_method = 1
+ij_groovy_blank_lines_around_method_in_interface = 1
+ij_groovy_blank_lines_before_imports = 1
+ij_groovy_blank_lines_before_method_body = 0
+ij_groovy_blank_lines_before_package = 0
+ij_groovy_block_brace_style = end_of_line
+ij_groovy_block_comment_at_first_column = true
+ij_groovy_call_parameters_new_line_after_left_paren = false
+ij_groovy_call_parameters_right_paren_on_new_line = false
+ij_groovy_call_parameters_wrap = off
+ij_groovy_catch_on_new_line = false
+ij_groovy_class_annotation_wrap = split_into_lines
+ij_groovy_class_brace_style = end_of_line
+ij_groovy_class_count_to_use_import_on_demand = 5
+ij_groovy_do_while_brace_force = never
+ij_groovy_else_on_new_line = false
+ij_groovy_enum_constants_wrap = off
+ij_groovy_extends_keyword_wrap = off
+ij_groovy_extends_list_wrap = off
+ij_groovy_field_annotation_wrap = off
+ij_groovy_finally_on_new_line = false
+ij_groovy_for_brace_force = never
+ij_groovy_for_statement_new_line_after_left_paren = false
+ij_groovy_for_statement_right_paren_on_new_line = false
+ij_groovy_for_statement_wrap = off
+ij_groovy_if_brace_force = never
+ij_groovy_import_annotation_wrap = 2
+ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
+ij_groovy_indent_case_from_switch = true
+ij_groovy_indent_label_blocks = true
+ij_groovy_insert_inner_class_imports = false
+ij_groovy_keep_blank_lines_before_right_brace = 2
+ij_groovy_keep_blank_lines_in_code = 2
+ij_groovy_keep_blank_lines_in_declarations = 2
+ij_groovy_keep_control_statement_in_one_line = true
+ij_groovy_keep_first_column_comment = true
+ij_groovy_keep_indents_on_empty_lines = false
+ij_groovy_keep_line_breaks = true
+ij_groovy_keep_multiple_expressions_in_one_line = false
+ij_groovy_keep_simple_blocks_in_one_line = false
+ij_groovy_keep_simple_classes_in_one_line = true
+ij_groovy_keep_simple_lambdas_in_one_line = true
+ij_groovy_keep_simple_methods_in_one_line = true
+ij_groovy_label_indent_absolute = false
+ij_groovy_label_indent_size = 0
+ij_groovy_lambda_brace_style = end_of_line
+ij_groovy_layout_static_imports_separately = true
+ij_groovy_line_comment_add_space = false
+ij_groovy_line_comment_at_first_column = true
+ij_groovy_method_annotation_wrap = off
+ij_groovy_method_brace_style = end_of_line
+ij_groovy_method_call_chain_wrap = off
+ij_groovy_method_parameters_new_line_after_left_paren = false
+ij_groovy_method_parameters_right_paren_on_new_line = false
+ij_groovy_method_parameters_wrap = off
+ij_groovy_modifier_list_wrap = false
+ij_groovy_names_count_to_use_import_on_demand = 3
+ij_groovy_parameter_annotation_wrap = off
+ij_groovy_parentheses_expression_new_line_after_left_paren = false
+ij_groovy_parentheses_expression_right_paren_on_new_line = false
+ij_groovy_prefer_parameters_wrap = false
+ij_groovy_resource_list_new_line_after_left_paren = false
+ij_groovy_resource_list_right_paren_on_new_line = false
+ij_groovy_resource_list_wrap = off
+ij_groovy_space_after_assert_separator = true
+ij_groovy_space_after_colon = true
+ij_groovy_space_after_comma = true
+ij_groovy_space_after_comma_in_type_arguments = true
+ij_groovy_space_after_for_semicolon = true
+ij_groovy_space_after_quest = true
+ij_groovy_space_after_type_cast = true
+ij_groovy_space_before_annotation_parameter_list = false
+ij_groovy_space_before_array_initializer_left_brace = false
+ij_groovy_space_before_assert_separator = false
+ij_groovy_space_before_catch_keyword = true
+ij_groovy_space_before_catch_left_brace = true
+ij_groovy_space_before_catch_parentheses = true
+ij_groovy_space_before_class_left_brace = true
+ij_groovy_space_before_closure_left_brace = true
+ij_groovy_space_before_colon = true
+ij_groovy_space_before_comma = false
+ij_groovy_space_before_do_left_brace = true
+ij_groovy_space_before_else_keyword = true
+ij_groovy_space_before_else_left_brace = true
+ij_groovy_space_before_finally_keyword = true
+ij_groovy_space_before_finally_left_brace = true
+ij_groovy_space_before_for_left_brace = true
+ij_groovy_space_before_for_parentheses = true
+ij_groovy_space_before_for_semicolon = false
+ij_groovy_space_before_if_left_brace = true
+ij_groovy_space_before_if_parentheses = true
+ij_groovy_space_before_method_call_parentheses = false
+ij_groovy_space_before_method_left_brace = true
+ij_groovy_space_before_method_parentheses = false
+ij_groovy_space_before_quest = true
+ij_groovy_space_before_switch_left_brace = true
+ij_groovy_space_before_switch_parentheses = true
+ij_groovy_space_before_synchronized_left_brace = true
+ij_groovy_space_before_synchronized_parentheses = true
+ij_groovy_space_before_try_left_brace = true
+ij_groovy_space_before_try_parentheses = true
+ij_groovy_space_before_while_keyword = true
+ij_groovy_space_before_while_left_brace = true
+ij_groovy_space_before_while_parentheses = true
+ij_groovy_space_in_named_argument = true
+ij_groovy_space_in_named_argument_before_colon = false
+ij_groovy_space_within_empty_array_initializer_braces = false
+ij_groovy_space_within_empty_method_call_parentheses = false
+ij_groovy_spaces_around_additive_operators = true
+ij_groovy_spaces_around_assignment_operators = true
+ij_groovy_spaces_around_bitwise_operators = true
+ij_groovy_spaces_around_equality_operators = true
+ij_groovy_spaces_around_lambda_arrow = true
+ij_groovy_spaces_around_logical_operators = true
+ij_groovy_spaces_around_multiplicative_operators = true
+ij_groovy_spaces_around_regex_operators = true
+ij_groovy_spaces_around_relational_operators = true
+ij_groovy_spaces_around_shift_operators = true
+ij_groovy_spaces_within_annotation_parentheses = false
+ij_groovy_spaces_within_array_initializer_braces = false
+ij_groovy_spaces_within_braces = true
+ij_groovy_spaces_within_brackets = false
+ij_groovy_spaces_within_cast_parentheses = false
+ij_groovy_spaces_within_catch_parentheses = false
+ij_groovy_spaces_within_for_parentheses = false
+ij_groovy_spaces_within_gstring_injection_braces = false
+ij_groovy_spaces_within_if_parentheses = false
+ij_groovy_spaces_within_list_or_map = false
+ij_groovy_spaces_within_method_call_parentheses = false
+ij_groovy_spaces_within_method_parentheses = false
+ij_groovy_spaces_within_parentheses = false
+ij_groovy_spaces_within_switch_parentheses = false
+ij_groovy_spaces_within_synchronized_parentheses = false
+ij_groovy_spaces_within_try_parentheses = false
+ij_groovy_spaces_within_tuple_expression = false
+ij_groovy_spaces_within_while_parentheses = false
+ij_groovy_special_else_if_treatment = true
+ij_groovy_ternary_operation_wrap = off
+ij_groovy_throws_keyword_wrap = off
+ij_groovy_throws_list_wrap = off
+ij_groovy_use_flying_geese_braces = false
+ij_groovy_use_fq_class_names = false
+ij_groovy_use_fq_class_names_in_javadoc = true
+ij_groovy_use_relative_indents = false
+ij_groovy_use_single_class_imports = true
+ij_groovy_variable_annotation_wrap = off
+ij_groovy_while_brace_force = never
+ij_groovy_while_on_new_line = false
+ij_groovy_wrap_long_lines = false
+
+[{*.kt,*.kts}]
+ij_kotlin_align_in_columns_case_branch = false
+ij_kotlin_align_multiline_binary_operation = false
+ij_kotlin_align_multiline_extends_list = false
+ij_kotlin_align_multiline_method_parentheses = false
+ij_kotlin_align_multiline_parameters = true
+ij_kotlin_align_multiline_parameters_in_calls = false
+ij_kotlin_allow_trailing_comma = true
+ij_kotlin_allow_trailing_comma_on_call_site = true
+ij_kotlin_assignment_wrap = off
+ij_kotlin_blank_lines_after_class_header = 0
+ij_kotlin_blank_lines_around_block_when_branches = 0
+ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
+ij_kotlin_block_comment_at_first_column = true
+ij_kotlin_call_parameters_new_line_after_left_paren = false
+ij_kotlin_call_parameters_right_paren_on_new_line = false
+ij_kotlin_call_parameters_wrap = off
+ij_kotlin_catch_on_new_line = false
+ij_kotlin_class_annotation_wrap = split_into_lines
+ij_kotlin_continuation_indent_for_chained_calls = true
+ij_kotlin_continuation_indent_for_expression_bodies = true
+ij_kotlin_continuation_indent_in_argument_lists = true
+ij_kotlin_continuation_indent_in_elvis = true
+ij_kotlin_continuation_indent_in_if_conditions = true
+ij_kotlin_continuation_indent_in_parameter_lists = true
+ij_kotlin_continuation_indent_in_supertype_lists = true
+ij_kotlin_else_on_new_line = false
+ij_kotlin_enum_constants_wrap = off
+ij_kotlin_extends_list_wrap = off
+ij_kotlin_field_annotation_wrap = on_every_item
+ij_kotlin_finally_on_new_line = false
+ij_kotlin_if_rparen_on_new_line = false
+ij_kotlin_import_nested_classes = false
+ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
+ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
+ij_kotlin_keep_blank_lines_before_right_brace = 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_at_first_column = true
+ij_kotlin_method_annotation_wrap = normal
+ij_kotlin_method_call_chain_wrap = off
+ij_kotlin_method_parameters_new_line_after_left_paren = false
+ij_kotlin_method_parameters_right_paren_on_new_line = false
+ij_kotlin_method_parameters_wrap = off
+ij_kotlin_name_count_to_use_star_import = 5
+ij_kotlin_name_count_to_use_star_import_for_members = 3
+ij_kotlin_packages_to_use_import_on_demand = java.util.*,io.ktor.**,java.awt.*,javax.swing.*
+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_variable_annotation_wrap = off
+ij_kotlin_while_on_new_line = false
+ij_kotlin_wrap_elvis_expressions = 1
+ij_kotlin_wrap_expression_body_functions = 0
+ij_kotlin_wrap_first_method_in_call_chain = false
+
+[{*.har,*.json}]
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = true
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{*.markdown,*.md}]
+ij_markdown_force_one_space_after_blockquote_symbol = true
+ij_markdown_force_one_space_after_header_symbol = true
+ij_markdown_force_one_space_after_list_bullet = true
+ij_markdown_force_one_space_between_words = true
+ij_markdown_keep_indents_on_empty_lines = false
+ij_markdown_max_lines_around_block_elements = 1
+ij_markdown_max_lines_around_header = 1
+ij_markdown_max_lines_between_paragraphs = 1
+ij_markdown_min_lines_around_block_elements = 1
+ij_markdown_min_lines_around_header = 1
+ij_markdown_min_lines_between_paragraphs = 1
+
+[{*.yaml,*.yml}]
+ij_yaml_keep_indents_on_empty_lines = false
+ij_yaml_keep_line_breaks = true
+ij_yaml_space_before_colon = true
+ij_yaml_spaces_within_braces = true
+ij_yaml_spaces_within_brackets = true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index aa35c5a..93a20c0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -125,22 +125,22 @@
@@ -159,12 +159,6 @@
android:exported="false"
android:label="@string/pref_customization_color_scheme"
android:theme="@style/AppTheme.NoActionBar.Dark"/>
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/java/io/neoterm/App.kt b/app/src/main/java/io/neoterm/App.kt
index 08612af..9b39d38 100644
--- a/app/src/main/java/io/neoterm/App.kt
+++ b/app/src/main/java/io/neoterm/App.kt
@@ -9,8 +9,8 @@ import android.view.Gravity
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import io.neoterm.component.NeoInitializer
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.ui.bonus.BonusActivity
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.ui.other.BonusActivity
import io.neoterm.utils.CrashHandler
/**
@@ -73,4 +73,4 @@ class App : Application() {
return app!!
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/NeoInitializer.kt b/app/src/main/java/io/neoterm/component/NeoInitializer.kt
index 1a7d867..e30678a 100644
--- a/app/src/main/java/io/neoterm/component/NeoInitializer.kt
+++ b/app/src/main/java/io/neoterm/component/NeoInitializer.kt
@@ -10,10 +10,9 @@ import io.neoterm.component.font.FontComponent
import io.neoterm.component.pm.PackageComponent
import io.neoterm.component.profile.ProfileComponent
import io.neoterm.component.session.SessionComponent
+import io.neoterm.component.session.ShellProfile
import io.neoterm.component.userscript.UserScriptComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.session.shell.ShellProfile
+import io.neoterm.utils.NLog
/**
* @author kiva
@@ -39,4 +38,4 @@ object NeoInitializer {
val profileComp = ComponentManager.getComponent()
profileComp.registerProfile(ShellProfile.PROFILE_META_NAME, ShellProfile::class.java)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/codegen/CodeGenParameter.kt b/app/src/main/java/io/neoterm/component/codegen/CodeGenParameter.kt
deleted file mode 100644
index 0d0170a..0000000
--- a/app/src/main/java/io/neoterm/component/codegen/CodeGenParameter.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.component.codegen
-
-/**
- * @author kiva
- */
-class CodeGenParameter
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/codegen/CodeGenComponent.kt b/app/src/main/java/io/neoterm/component/codegen/comp.kt
similarity index 64%
rename from app/src/main/java/io/neoterm/component/codegen/CodeGenComponent.kt
rename to app/src/main/java/io/neoterm/component/codegen/comp.kt
index ec78f3d..4ffcb47 100644
--- a/app/src/main/java/io/neoterm/component/codegen/CodeGenComponent.kt
+++ b/app/src/main/java/io/neoterm/component/codegen/comp.kt
@@ -1,12 +1,8 @@
package io.neoterm.component.codegen
-import io.neoterm.component.codegen.interfaces.CodeGenObject
-import io.neoterm.component.codegen.interfaces.CodeGenerator
-import io.neoterm.frontend.component.NeoComponent
+import io.neoterm.component.NeoComponent
+
-/**
- * @author kiva
- */
class CodeGenComponent : NeoComponent {
override fun onServiceInit() {
}
@@ -23,3 +19,4 @@ class CodeGenComponent : NeoComponent {
}
}
+class CodeGenParameter
diff --git a/app/src/main/java/io/neoterm/component/codegen/generators/NeoColorGenerator.kt b/app/src/main/java/io/neoterm/component/codegen/generators.kt
similarity index 84%
rename from app/src/main/java/io/neoterm/component/codegen/generators/NeoColorGenerator.kt
rename to app/src/main/java/io/neoterm/component/codegen/generators.kt
index a0ef650..3ceb7f2 100644
--- a/app/src/main/java/io/neoterm/component/codegen/generators/NeoColorGenerator.kt
+++ b/app/src/main/java/io/neoterm/component/codegen/generators.kt
@@ -1,15 +1,9 @@
-package io.neoterm.component.codegen.generators
+package io.neoterm.component.codegen
-import io.neoterm.component.codegen.CodeGenParameter
-import io.neoterm.component.codegen.interfaces.CodeGenObject
-import io.neoterm.component.codegen.interfaces.CodeGenerator
+import io.neoterm.component.ComponentManager
import io.neoterm.component.colorscheme.NeoColorScheme
import io.neoterm.component.config.ConfigureComponent
-import io.neoterm.frontend.component.ComponentManager
-/**
- * @author kiva
- */
class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
override fun getGeneratorName(): String {
return "NeoColorScheme-Generator"
@@ -44,7 +38,7 @@ class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter)
" ${NeoColorScheme.COLOR_META_VERSION}: ${
colorScheme.colorVersion
?: component.getLoaderVersion()
- }\n"
+ }\n",
)
builder.append("\n")
}
@@ -61,4 +55,14 @@ class NeoColorGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter)
builder.append(" }\n")
}
-}
\ No newline at end of file
+}
+
+class NeoProfileGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
+ override fun getGeneratorName(): String {
+ return "NeoProfile-Generator"
+ }
+
+ override fun generateCode(codeGenObject: CodeGenObject): String {
+ return ""
+ }
+}
diff --git a/app/src/main/java/io/neoterm/component/codegen/generators/NeoProfileGenerator.kt b/app/src/main/java/io/neoterm/component/codegen/generators/NeoProfileGenerator.kt
deleted file mode 100644
index 3fb2209..0000000
--- a/app/src/main/java/io/neoterm/component/codegen/generators/NeoProfileGenerator.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.neoterm.component.codegen.generators
-
-import io.neoterm.component.codegen.CodeGenParameter
-import io.neoterm.component.codegen.interfaces.CodeGenObject
-import io.neoterm.component.codegen.interfaces.CodeGenerator
-
-/**
- * @author kiva
- */
-class NeoProfileGenerator(parameter: CodeGenParameter) : CodeGenerator(parameter) {
- override fun getGeneratorName(): String {
- return "NeoProfile-Generator"
- }
-
- override fun generateCode(codeGenObject: CodeGenObject): String {
- return ""
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenerator.kt b/app/src/main/java/io/neoterm/component/codegen/interfaces.kt
similarity index 56%
rename from app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenerator.kt
rename to app/src/main/java/io/neoterm/component/codegen/interfaces.kt
index b4a25c3..30441cd 100644
--- a/app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenerator.kt
+++ b/app/src/main/java/io/neoterm/component/codegen/interfaces.kt
@@ -1,12 +1,10 @@
-package io.neoterm.component.codegen.interfaces
+package io.neoterm.component.codegen
-import io.neoterm.component.codegen.CodeGenParameter
-
-/**
- * @author kiva
- */
abstract class CodeGenerator(parameter: CodeGenParameter) {
abstract fun getGeneratorName(): String
-
abstract fun generateCode(codeGenObject: CodeGenObject): String
}
+
+interface CodeGenObject {
+ fun getCodeGenerator(parameter: CodeGenParameter): CodeGenerator
+}
diff --git a/app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenObject.kt b/app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenObject.kt
deleted file mode 100644
index abf69ca..0000000
--- a/app/src/main/java/io/neoterm/component/codegen/interfaces/CodeGenObject.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.component.codegen.interfaces
-
-import io.neoterm.component.codegen.CodeGenParameter
-
-/**
- * @author kiva
- */
-interface CodeGenObject {
- fun getCodeGenerator(parameter: CodeGenParameter): CodeGenerator
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/colorscheme/DefaultColorScheme.kt b/app/src/main/java/io/neoterm/component/colorscheme/DefaultColorScheme.kt
deleted file mode 100644
index 694a7ec..0000000
--- a/app/src/main/java/io/neoterm/component/colorscheme/DefaultColorScheme.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.neoterm.component.colorscheme
-
-/**
- * @author kiva
- */
-object DefaultColorScheme : NeoColorScheme() {
- init {
- /* NOTE: Keep in sync with assets/colors/Default.nl */
- colorName = "Default"
-
- foregroundColor = "#ffffff"
- backgroundColor = "#14181c"
- cursorColor = "#a9aaa9"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/colorscheme/ColorSchemeComponent.kt b/app/src/main/java/io/neoterm/component/colorscheme/comp.kt
similarity index 91%
rename from app/src/main/java/io/neoterm/component/colorscheme/ColorSchemeComponent.kt
rename to app/src/main/java/io/neoterm/component/colorscheme/comp.kt
index f855c5f..cb6563b 100644
--- a/app/src/main/java/io/neoterm/component/colorscheme/ColorSchemeComponent.kt
+++ b/app/src/main/java/io/neoterm/component/colorscheme/comp.kt
@@ -4,20 +4,17 @@ import android.content.Context
import io.neolang.visitor.ConfigVisitor
import io.neoterm.App
import io.neoterm.R
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.ConfigFileBasedComponent
import io.neoterm.component.codegen.CodeGenComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
import io.neoterm.utils.extractAssetsDir
import java.io.File
import java.nio.file.Files
-/**
- * @author kiva
- */
class ColorSchemeComponent : ConfigFileBasedComponent(NeoTermPath.COLORS_PATH) {
companion object {
fun colorFile(colorName: String): File {
@@ -120,4 +117,5 @@ class ColorSchemeComponent : ConfigFileBasedComponent(NeoTermPat
throw RuntimeException("Failed to save file ${colorFile.absolutePath}")
}
}
-}
\ No newline at end of file
+}
+
diff --git a/app/src/main/java/io/neoterm/component/colorscheme/NeoColorScheme.kt b/app/src/main/java/io/neoterm/component/colorscheme/data.kt
similarity index 80%
rename from app/src/main/java/io/neoterm/component/colorscheme/NeoColorScheme.kt
rename to app/src/main/java/io/neoterm/component/colorscheme/data.kt
index 4373009..04ec525 100644
--- a/app/src/main/java/io/neoterm/component/colorscheme/NeoColorScheme.kt
+++ b/app/src/main/java/io/neoterm/component/colorscheme/data.kt
@@ -3,23 +3,15 @@ package io.neoterm.component.colorscheme
import io.neolang.visitor.ConfigVisitor
import io.neoterm.backend.TerminalColorScheme
import io.neoterm.backend.TerminalColors
+import io.neoterm.component.ConfigFileBasedObject
+import io.neoterm.component.codegen.CodeGenObject
import io.neoterm.component.codegen.CodeGenParameter
-import io.neoterm.component.codegen.generators.NeoColorGenerator
-import io.neoterm.component.codegen.interfaces.CodeGenObject
-import io.neoterm.component.codegen.interfaces.CodeGenerator
-import io.neoterm.component.config.ConfigureComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.component.helper.ConfigFileBasedObject
-import io.neoterm.frontend.config.NeoConfigureFile
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
-import org.jetbrains.annotations.TestOnly
-import java.io.File
+import io.neoterm.component.codegen.CodeGenerator
+import io.neoterm.component.codegen.NeoColorGenerator
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
+import io.neoterm.utils.NLog
-/**
- * @author kiva
- */
open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
companion object {
const val COLOR_PREFIX = "color"
@@ -173,24 +165,15 @@ open class NeoColorScheme : CodeGenObject, ConfigFileBasedObject {
private fun getColorByVisitor(visitor: ConfigVisitor, colorName: String): String? {
return visitor.getStringValue(COLOR_PATH, colorName)
}
+}
- @TestOnly
- fun testLoadConfigure(file: File): Boolean {
- val loaderService = ComponentManager.getComponent()
+object DefaultColorScheme : NeoColorScheme() {
+ init {
+ /* NOTE: Keep in sync with assets/colors/Default.nl */
+ colorName = "Default"
- val configure: NeoConfigureFile?
- try {
- configure = loaderService.newLoader(file).loadConfigure()
- if (configure == null) {
- throw RuntimeException("Parse configuration failed.")
- }
- } catch (e: Exception) {
- NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: ${e.localizedMessage}")
- return false
- }
-
- val visitor = configure.getVisitor()
- onConfigLoaded(visitor)
- return true
+ foregroundColor = "#ffffff"
+ backgroundColor = "#14181c"
+ cursorColor = "#a9aaa9"
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/component/ComponentManager.kt b/app/src/main/java/io/neoterm/component/comp.kt
similarity index 79%
rename from app/src/main/java/io/neoterm/frontend/component/ComponentManager.kt
rename to app/src/main/java/io/neoterm/component/comp.kt
index b4b5f25..da0e529 100644
--- a/app/src/main/java/io/neoterm/frontend/component/ComponentManager.kt
+++ b/app/src/main/java/io/neoterm/component/comp.kt
@@ -1,10 +1,13 @@
-package io.neoterm.frontend.component
+package io.neoterm.component
import java.util.concurrent.ConcurrentHashMap
-/**
- * @author kiva
- */
+interface NeoComponent {
+ fun onServiceInit()
+ fun onServiceDestroy()
+ fun onServiceObtained()
+}
+
object ComponentManager {
private val COMPONENTS = ConcurrentHashMap, NeoComponent>()
@@ -43,3 +46,7 @@ object ComponentManager {
return componentInterface.newInstance()
}
}
+
+class ComponentDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")
+class ComponentNotFoundException(serviceName: String) : RuntimeException("Component `$serviceName' not found")
+
diff --git a/app/src/main/java/io/neoterm/component/completion/CompletionComponent.kt b/app/src/main/java/io/neoterm/component/completion/CompletionComponent.kt
deleted file mode 100644
index 428960f..0000000
--- a/app/src/main/java/io/neoterm/component/completion/CompletionComponent.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.neoterm.component.completion
-
-import io.neoterm.component.completion.provider.FileCompletionProvider
-import io.neoterm.component.completion.provider.ProgramCompletionProvider
-import io.neoterm.frontend.completion.CompletionManager
-import io.neoterm.frontend.component.NeoComponent
-
-/**
- * @author kiva
- */
-class CompletionComponent : NeoComponent {
- override fun onServiceInit() {
- CompletionManager.registerProvider(FileCompletionProvider())
- CompletionManager.registerProvider(ProgramCompletionProvider())
- }
-
- override fun onServiceDestroy() {
- }
-
- override fun onServiceObtained() {
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/completion/CompletionManager.kt b/app/src/main/java/io/neoterm/component/completion/comp.kt
similarity index 55%
rename from app/src/main/java/io/neoterm/frontend/completion/CompletionManager.kt
rename to app/src/main/java/io/neoterm/component/completion/comp.kt
index a7d69ca..e6bad82 100644
--- a/app/src/main/java/io/neoterm/frontend/completion/CompletionManager.kt
+++ b/app/src/main/java/io/neoterm/component/completion/comp.kt
@@ -1,11 +1,20 @@
-package io.neoterm.frontend.completion
+package io.neoterm.component.completion
-import io.neoterm.frontend.completion.model.CompletionResult
-import io.neoterm.frontend.completion.provider.ICandidateProvider
+import io.neoterm.component.NeoComponent
+
+class CompletionComponent : NeoComponent {
+ override fun onServiceInit() {
+ CompletionManager.registerProvider(FileCompletionProvider())
+ CompletionManager.registerProvider(ProgramCompletionProvider())
+ }
+
+ override fun onServiceDestroy() {
+ }
+
+ override fun onServiceObtained() {
+ }
+}
-/**
- * @author kiva
- */
object CompletionManager {
private val candidateProviders = mutableMapOf()
@@ -37,4 +46,23 @@ object CompletionManager {
return ProviderDetector(candidateProviders.values
.takeWhile { it.canComplete(text) })
}
-}
\ No newline at end of file
+}
+
+class ProviderDetector(val providers: List) : MarkScoreListener {
+ private var detectedProvider: ICandidateProvider? = null
+
+ override fun onMarkScore(score: Int) {
+ // TODO: Save provider score
+ }
+
+ fun detectBest(): ICandidateProvider? {
+ // TODO: detect best
+ detectedProvider = if (providers.isEmpty())
+ null
+ else
+ providers[0]
+
+ return detectedProvider
+ }
+}
+
diff --git a/app/src/main/java/io/neoterm/frontend/completion/model/CompletionResult.kt b/app/src/main/java/io/neoterm/component/completion/data.kt
similarity index 58%
rename from app/src/main/java/io/neoterm/frontend/completion/model/CompletionResult.kt
rename to app/src/main/java/io/neoterm/component/completion/data.kt
index 6069191..5b7acaf 100644
--- a/app/src/main/java/io/neoterm/frontend/completion/model/CompletionResult.kt
+++ b/app/src/main/java/io/neoterm/component/completion/data.kt
@@ -1,10 +1,10 @@
-package io.neoterm.frontend.completion.model
+package io.neoterm.component.completion
-import io.neoterm.frontend.completion.listener.MarkScoreListener
+class CompletionCandidate(val completeString: String) {
+ var displayName: String = completeString
+ var description: String? = null
+}
-/**
- * @author kiva
- */
class CompletionResult(val candidates: List, var scoreMarker: MarkScoreListener) {
fun markScore(score: Int) {
scoreMarker.onMarkScore(score)
@@ -13,4 +13,5 @@ class CompletionResult(val candidates: List, var scoreMarke
fun hasResult(): Boolean {
return candidates.isNotEmpty()
}
-}
\ No newline at end of file
+}
+
diff --git a/app/src/main/java/io/neoterm/component/completion/listeners.kt b/app/src/main/java/io/neoterm/component/completion/listeners.kt
new file mode 100644
index 0000000..944388e
--- /dev/null
+++ b/app/src/main/java/io/neoterm/component/completion/listeners.kt
@@ -0,0 +1,16 @@
+package io.neoterm.component.completion
+
+interface MarkScoreListener {
+ fun onMarkScore(score: Int)
+}
+
+interface OnAutoCompleteListener {
+ fun onCompletionRequired(newText: String?)
+ fun onKeyCode(keyCode: Int, keyMod: Int)
+ fun onCleanUp()
+ fun onFinishCompletion(): Boolean
+}
+
+interface OnCandidateSelectedListener {
+ fun onCandidateSelected(candidate: CompletionCandidate)
+}
diff --git a/app/src/main/java/io/neoterm/component/completion/provider/ProgramCompletionProvider.kt b/app/src/main/java/io/neoterm/component/completion/provider/ProgramCompletionProvider.kt
deleted file mode 100644
index 79aa12c..0000000
--- a/app/src/main/java/io/neoterm/component/completion/provider/ProgramCompletionProvider.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.neoterm.component.completion.provider
-
-import java.io.File
-
-/**
- * @author kiva
- */
-class ProgramCompletionProvider : FileCompletionProvider() {
- override val providerName: String
- get() = "NeoTermProvider.ProgramCompletionProvider"
-
-
- override fun generateDesc(file: File): String? {
- return if (file.canExecute()) "" else super.generateDesc(file)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/completion/provider/FileCompletionProvider.kt b/app/src/main/java/io/neoterm/component/completion/providers.kt
similarity index 58%
rename from app/src/main/java/io/neoterm/component/completion/provider/FileCompletionProvider.kt
rename to app/src/main/java/io/neoterm/component/completion/providers.kt
index f6bcdb8..c86a0e0 100644
--- a/app/src/main/java/io/neoterm/component/completion/provider/FileCompletionProvider.kt
+++ b/app/src/main/java/io/neoterm/component/completion/providers.kt
@@ -1,18 +1,18 @@
-package io.neoterm.component.completion.provider
+package io.neoterm.component.completion
-import io.neoterm.frontend.completion.model.CompletionCandidate
-import io.neoterm.frontend.completion.provider.ICandidateProvider
import java.io.File
-/**
- * @author kiva
- */
+interface ICandidateProvider {
+ val providerName: String
+ fun provideCandidates(text: String): List
+ fun canComplete(text: String): Boolean
+}
open class FileCompletionProvider : ICandidateProvider {
override val providerName: String
get() = "NeoTermProvider.FileCompletionProvider"
- override fun provideCandidates(text: String): List? {
+ override fun provideCandidates(text: String): List {
var file = File(text)
var filter: ((File) -> Boolean)? = null
@@ -33,20 +33,14 @@ open class FileCompletionProvider : ICandidateProvider {
return if (filter != null) path.listFiles(filter) else path.listFiles()
}
- private fun generateCandidateList(file: File, filter: ((File) -> Boolean)?): List? {
- if (file.canRead()) {
- val candidates = mutableListOf()
- listDirectory(file, filter)
- .mapTo(candidates, {
- val candidate = CompletionCandidate(it.name)
- candidate.description = generateDesc(it)
- candidate.displayName = generateDisplayName(it)
- candidate
- })
- return candidates
- }
- return null
- }
+ private fun generateCandidateList(file: File, filter: ((File) -> Boolean)?) =
+ if (file.canRead()) listDirectory(file, filter).map {
+ val candidate = CompletionCandidate(it.name)
+ candidate.description = generateDesc(it)
+ candidate.displayName = generateDisplayName(it)
+ candidate
+ }.toList()
+ else listOf()
open fun generateDisplayName(file: File): String {
return if (file.isDirectory) "${file.name}/" else file.name
@@ -56,3 +50,13 @@ open class FileCompletionProvider : ICandidateProvider {
return null
}
}
+
+class ProgramCompletionProvider : FileCompletionProvider() {
+ override val providerName: String
+ get() = "NeoTermProvider.ProgramCompletionProvider"
+
+
+ override fun generateDesc(file: File): String? {
+ return if (file.canExecute()) "" else super.generateDesc(file)
+ }
+}
diff --git a/app/src/main/java/io/neoterm/component/config/ConfigureComponent.kt b/app/src/main/java/io/neoterm/component/config/ConfigureComponent.kt
deleted file mode 100644
index 02c8d09..0000000
--- a/app/src/main/java/io/neoterm/component/config/ConfigureComponent.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.neoterm.component.config
-
-import io.neoterm.component.config.loaders.NeoLangConfigureLoader
-import io.neoterm.component.config.loaders.OldConfigureLoader
-import io.neoterm.frontend.component.NeoComponent
-import java.io.File
-
-/**
- * @author kiva
- */
-class ConfigureComponent : NeoComponent {
- val CONFIG_LOADER_VERSION = 20
-
- override fun onServiceInit() {
- }
-
- override fun onServiceDestroy() {
- }
-
- override fun onServiceObtained() {
- }
-
- fun getLoaderVersion(): Int {
- return CONFIG_LOADER_VERSION
- }
-
- fun newLoader(configFile: File): IConfigureLoader {
- return when (configFile.extension) {
- "nl" -> NeoLangConfigureLoader(configFile)
- else -> OldConfigureLoader(configFile)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/config/IConfigureLoader.kt b/app/src/main/java/io/neoterm/component/config/IConfigureLoader.kt
deleted file mode 100644
index 78cae91..0000000
--- a/app/src/main/java/io/neoterm/component/config/IConfigureLoader.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.component.config
-
-import io.neoterm.frontend.config.NeoConfigureFile
-
-/**
- * @author kiva
- */
-interface IConfigureLoader {
- fun loadConfigure(): NeoConfigureFile?
-}
diff --git a/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt b/app/src/main/java/io/neoterm/component/config/comp.kt
similarity index 84%
rename from app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt
rename to app/src/main/java/io/neoterm/component/config/comp.kt
index dbf7437..d44c728 100644
--- a/app/src/main/java/io/neoterm/frontend/config/NeoPreference.kt
+++ b/app/src/main/java/io/neoterm/component/config/comp.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.config
+package io.neoterm.component.config
import android.content.Context
import android.content.SharedPreferences
@@ -6,18 +6,59 @@ import android.preference.PreferenceManager
import android.system.ErrnoException
import android.system.Os
import android.util.TypedValue
+import io.neolang.parser.NeoLangParser
+import io.neolang.visitor.ConfigVisitor
import io.neoterm.App
import io.neoterm.R
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.component.NeoComponent
import io.neoterm.services.NeoTermService
+import io.neoterm.utils.NLog
import java.io.File
import java.nio.file.Files
+class ConfigureComponent : NeoComponent {
+ override fun onServiceInit() {
+ }
-/**
- * @author kiva
- */
+ override fun onServiceDestroy() {
+ }
+
+ override fun onServiceObtained() {
+ }
+
+ fun getLoaderVersion(): Int {
+ return CONFIG_LOADER_VERSION
+ }
+
+ fun newLoader(configFile: File): IConfigureLoader {
+ return when (configFile.extension) {
+ "nl" -> NeoLangConfigureLoader(configFile)
+ else -> OldConfigureLoader(configFile)
+ }
+ }
+
+ companion object {
+ private const val CONFIG_LOADER_VERSION = 20
+ }
+}
+
+open class NeoConfigureFile(val configureFile: File) {
+ private val configParser = NeoLangParser()
+ protected open var configVisitor: ConfigVisitor? = null
+
+ fun getVisitor() = configVisitor ?: throw IllegalStateException("Configure file not loaded or parse failed.")
+
+ open fun parseConfigure() = kotlin.runCatching {
+ val programCode = String(Files.readAllBytes(configureFile.toPath()))
+ configParser.setInputSource(programCode)
+
+ val ast = configParser.parse()
+ val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
+ astVisitor.start()
+ configVisitor = astVisitor.getCallback()
+ }.isSuccess
+}
object NeoPreference {
const val KEY_HAPPY_EGG = "neoterm_fun_happy"
diff --git a/app/src/main/java/io/neoterm/frontend/config/NeoTermPath.kt b/app/src/main/java/io/neoterm/component/config/defaults.kt
similarity index 59%
rename from app/src/main/java/io/neoterm/frontend/config/NeoTermPath.kt
rename to app/src/main/java/io/neoterm/component/config/defaults.kt
index ad211d4..eaf2d34 100644
--- a/app/src/main/java/io/neoterm/frontend/config/NeoTermPath.kt
+++ b/app/src/main/java/io/neoterm/component/config/defaults.kt
@@ -1,10 +1,28 @@
-package io.neoterm.frontend.config
+package io.neoterm.component.config
import android.annotation.SuppressLint
-/**
- * @author kiva
- */
+object DefaultValues {
+ const val fontSize = 30
+
+ const val enableBell = false
+ const val enableVibrate = false
+ const val enableExecveWrapper = true
+ const val enableAutoCompletion = false
+ const val enableFullScreen = false
+ const val enableAutoHideToolbar = false
+ const val enableSwitchNextTab = false
+ const val enableExtraKeys = true
+ const val enableExplicitExtraKeysWeight = false
+ const val enableBackButtonBeMappedToEscape = false
+ const val enableSpecialVolumeKeys = false
+ const val enableWordBasedIme = false
+
+ const val loginShell = "bash"
+ const val initialCommand = ""
+ const val defaultFont = "SourceCodePro"
+}
+
object NeoTermPath {
@SuppressLint("SdCardPath")
const val ROOT_PATH = "/data/data/io.neoterm/files"
@@ -32,4 +50,4 @@ object NeoTermPath {
init {
DEFAULT_MAIN_PACKAGE_SOURCE = SOURCE
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/config/loaders.kt b/app/src/main/java/io/neoterm/component/config/loaders.kt
new file mode 100644
index 0000000..39c610a
--- /dev/null
+++ b/app/src/main/java/io/neoterm/component/config/loaders.kt
@@ -0,0 +1,194 @@
+package io.neoterm.component.config
+
+import io.neolang.runtime.type.NeoLangValue
+import io.neolang.visitor.ConfigVisitor
+import io.neoterm.component.colorscheme.NeoColorScheme
+import io.neoterm.component.extrakey.NeoExtraKey
+import io.neoterm.frontend.session.view.extrakey.TextButton
+import io.neoterm.utils.NLog
+import java.io.BufferedReader
+import java.io.File
+import java.io.FileInputStream
+import java.io.FileReader
+import java.util.*
+
+interface IConfigureLoader {
+ fun loadConfigure(): NeoConfigureFile?
+}
+
+class NeoLangConfigureLoader(private val configFile: File) : IConfigureLoader {
+ override fun loadConfigure(): NeoConfigureFile? {
+ val configureFile = NeoConfigureFile(configFile)
+ return if (configureFile.parseConfigure()) configureFile else null
+ }
+}
+
+class OldConfigureLoader(private val configFile: File) : IConfigureLoader {
+ override fun loadConfigure(): NeoConfigureFile? {
+ return when (configFile.extension) {
+ "eks" -> returnConfigure(OldExtraKeysConfigureFile(configFile))
+ "color" -> returnConfigure(OldColorSchemeConfigureFile(configFile))
+ else -> null
+ }
+ }
+
+ private fun returnConfigure(configureFile: NeoConfigureFile): NeoConfigureFile? {
+ return if (configureFile.parseConfigure()) configureFile else null
+ }
+
+ companion object {
+ class OldColorSchemeConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
+ override var configVisitor: ConfigVisitor? = null
+
+ override fun parseConfigure(): Boolean {
+ try {
+ val visitor = ConfigVisitor()
+ visitor.onStart()
+ visitor.onEnterContext(NeoColorScheme.CONTEXT_META_NAME)
+
+ visitor.getCurrentContext()
+ .defineAttribute(NeoColorScheme.COLOR_META_NAME, NeoLangValue(configureFile.nameWithoutExtension))
+ .defineAttribute(NeoColorScheme.COLOR_META_VERSION, NeoLangValue("1.0"))
+
+ visitor.onEnterContext(NeoColorScheme.CONTEXT_COLOR_NAME)
+
+ return FileInputStream(configureFile).use {
+ val prop = Properties()
+ prop.load(it)
+ prop.forEach {
+ visitor.getCurrentContext().defineAttribute(it.key as String, NeoLangValue(it.value as String))
+ }
+ visitor.onFinish()
+ this.configVisitor = visitor
+ true
+ }
+
+ } catch (e: Exception) {
+ this.configVisitor = null
+ NLog.e("ConfigureLoader", "Error while loading old config", e)
+ return false
+ }
+ }
+ }
+ class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
+ override var configVisitor: ConfigVisitor? = null
+
+ override fun parseConfigure(): Boolean {
+ try {
+ val config = parseOldConfig(BufferedReader(FileReader(configureFile)))
+ return generateVisitor(config)
+ } catch (e: Exception) {
+ NLog.e("ConfigureLoader", "Failed to load old extra keys config: ${e.localizedMessage}")
+ return false
+ }
+ }
+
+ private fun generateVisitor(config: NeoExtraKey): Boolean {
+ configVisitor = ConfigVisitor()
+ val visitor = configVisitor!!
+ visitor.onStart()
+ visitor.onEnterContext(NeoExtraKey.EKS_META_CONTEXT_NAME)
+ visitor.getCurrentContext()
+ .defineAttribute(NeoExtraKey.EKS_META_VERSION, NeoLangValue(config.version))
+ .defineAttribute(NeoExtraKey.EKS_META_WITH_DEFAULT, NeoLangValue(config.withDefaultKeys))
+
+ // program
+ visitor.onEnterContext(NeoExtraKey.EKS_META_PROGRAM)
+ config.programNames.forEachIndexed { index, program ->
+ visitor.getCurrentContext().defineAttribute(index.toString(), NeoLangValue(program))
+ }
+ visitor.onExitContext()
+
+ // key
+ visitor.onEnterContext(NeoExtraKey.EKS_META_KEY)
+ config.shortcutKeys.forEachIndexed { index, button ->
+ if (button is TextButton) {
+ visitor.onEnterContext(index.toString())
+ visitor.getCurrentContext()
+ .defineAttribute(NeoExtraKey.EKS_META_WITH_ENTER, NeoLangValue(button.withEnter))
+ .defineAttribute(NeoExtraKey.EKS_META_DISPLAY, NeoLangValue(button.buttonKeys!!))
+ .defineAttribute(NeoExtraKey.EKS_META_CODE, NeoLangValue(button.buttonKeys!!))
+ visitor.onExitContext()
+ }
+ }
+ visitor.onExitContext()
+
+ visitor.onFinish()
+ return true
+ }
+
+ private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
+ val config = NeoExtraKey()
+ var line: String? = source.readLine()
+
+ while (line != null) {
+ line = line.trim().trimEnd()
+ if (line.isEmpty() || line.startsWith("#")) {
+ line = source.readLine()
+ continue
+ }
+
+ if (line.startsWith(NeoExtraKey.EKS_META_VERSION)) {
+ parseHeader(line, config)
+ } else if (line.startsWith(NeoExtraKey.EKS_META_PROGRAM)) {
+ parseProgram(line, config)
+ } else if (line.startsWith("define")) {
+ parseKeyDefine(line, config)
+ } else if (line.startsWith(NeoExtraKey.EKS_META_WITH_DEFAULT)) {
+ parseWithDefault(line, config)
+ }
+ line = source.readLine()
+ }
+
+ if (config.version < 0) {
+ throw RuntimeException("Not a valid shortcut config file")
+ }
+ if (config.programNames.size == 0) {
+ throw RuntimeException("At least one program name should be given")
+ }
+ return config
+ }
+
+ private fun parseWithDefault(line: String, config: NeoExtraKey) {
+ val value = line.substring(NeoExtraKey.EKS_META_WITH_DEFAULT.length).trim().trimEnd()
+ config.withDefaultKeys = value == "true"
+ }
+
+ private fun parseKeyDefine(line: String, config: NeoExtraKey) {
+ val keyDefine = line.substring("define".length).trim().trimEnd()
+ val keyValues = keyDefine.split(" ")
+ if (keyValues.size < 2) {
+ throw RuntimeException("Bad define")
+ }
+
+ val buttonText = keyValues[0]
+ val withEnter = keyValues[1] == "true"
+
+ config.shortcutKeys.add(TextButton(buttonText, withEnter))
+ }
+
+ private fun parseProgram(line: String, config: NeoExtraKey) {
+ val programNames = line.substring(NeoExtraKey.EKS_META_PROGRAM.length).trim().trimEnd()
+ if (programNames.isEmpty()) {
+ return
+ }
+
+ for (name in programNames.split(" ")) {
+ config.programNames.add(name)
+ }
+ }
+
+ private fun parseHeader(line: String, config: NeoExtraKey) {
+ val version: Int
+ val versionString = line.substring(NeoExtraKey.EKS_META_VERSION.length).trim().trimEnd()
+ try {
+ version = Integer.parseInt(versionString)
+ } catch (e: NumberFormatException) {
+ throw RuntimeException("Bad version '$versionString'")
+ }
+
+ config.version = version
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/io/neoterm/component/config/loaders/NeoLangConfigureLoader.kt b/app/src/main/java/io/neoterm/component/config/loaders/NeoLangConfigureLoader.kt
deleted file mode 100644
index 95391d4..0000000
--- a/app/src/main/java/io/neoterm/component/config/loaders/NeoLangConfigureLoader.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.neoterm.component.config.loaders
-
-import io.neoterm.component.config.IConfigureLoader
-import io.neoterm.frontend.config.NeoConfigureFile
-import java.io.File
-
-/**
- * @author kiva
- */
-class NeoLangConfigureLoader(private val configFile: File) : IConfigureLoader {
- override fun loadConfigure(): NeoConfigureFile? {
- val configureFile = NeoConfigureFile(configFile)
- return if (configureFile.parseConfigure()) configureFile else null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/config/loaders/OldColorSchemeConfigureFile.kt b/app/src/main/java/io/neoterm/component/config/loaders/OldColorSchemeConfigureFile.kt
deleted file mode 100644
index f4d2a50..0000000
--- a/app/src/main/java/io/neoterm/component/config/loaders/OldColorSchemeConfigureFile.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.neoterm.component.config.loaders
-
-import io.neolang.runtime.type.NeoLangValue
-import io.neolang.visitor.ConfigVisitor
-import io.neoterm.component.colorscheme.NeoColorScheme
-import io.neoterm.frontend.config.NeoConfigureFile
-import io.neoterm.frontend.logging.NLog
-import java.io.File
-import java.io.FileInputStream
-import java.util.*
-
-/**
- * @author kiva
- */
-class OldColorSchemeConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
- override var configVisitor: ConfigVisitor? = null
-
- override fun parseConfigure(): Boolean {
- try {
- val visitor = ConfigVisitor()
- visitor.onStart()
- visitor.onEnterContext(NeoColorScheme.CONTEXT_META_NAME)
-
- visitor.getCurrentContext()
- .defineAttribute(NeoColorScheme.COLOR_META_NAME, NeoLangValue(configureFile.nameWithoutExtension))
- .defineAttribute(NeoColorScheme.COLOR_META_VERSION, NeoLangValue("1.0"))
-
- visitor.onEnterContext(NeoColorScheme.CONTEXT_COLOR_NAME)
-
- return FileInputStream(configureFile).use {
- val prop = Properties()
- prop.load(it)
- prop.forEach {
- visitor.getCurrentContext().defineAttribute(it.key as String, NeoLangValue(it.value as String))
- }
- visitor.onFinish()
- this.configVisitor = visitor
- true
- }
-
- } catch (e: Exception) {
- this.configVisitor = null
- NLog.e("ConfigureLoader", "Error while loading old config", e)
- return false
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/config/loaders/OldConfigureLoader.kt b/app/src/main/java/io/neoterm/component/config/loaders/OldConfigureLoader.kt
deleted file mode 100644
index ff73d55..0000000
--- a/app/src/main/java/io/neoterm/component/config/loaders/OldConfigureLoader.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.neoterm.component.config.loaders
-
-import io.neoterm.component.config.IConfigureLoader
-import io.neoterm.frontend.config.NeoConfigureFile
-import java.io.File
-
-/**
- * @author kiva
- */
-class OldConfigureLoader(private val configFile: File) : IConfigureLoader {
- override fun loadConfigure(): NeoConfigureFile? {
- return when (configFile.extension) {
- "eks" -> returnConfigure(OldExtraKeysConfigureFile(configFile))
- "color" -> returnConfigure(OldColorSchemeConfigureFile(configFile))
- else -> null
- }
- }
-
- private fun returnConfigure(configureFile: NeoConfigureFile): NeoConfigureFile? {
- return if (configureFile.parseConfigure()) configureFile else null
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/config/loaders/OldExtraKeysConfigureFile.kt b/app/src/main/java/io/neoterm/component/config/loaders/OldExtraKeysConfigureFile.kt
deleted file mode 100644
index e2a1a28..0000000
--- a/app/src/main/java/io/neoterm/component/config/loaders/OldExtraKeysConfigureFile.kt
+++ /dev/null
@@ -1,135 +0,0 @@
-package io.neoterm.component.config.loaders
-
-import io.neolang.runtime.type.NeoLangValue
-import io.neolang.visitor.ConfigVisitor
-import io.neoterm.component.extrakey.NeoExtraKey
-import io.neoterm.frontend.config.NeoConfigureFile
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.terminal.extrakey.button.TextButton
-import java.io.BufferedReader
-import java.io.File
-import java.io.FileReader
-
-/**
- * @author kiva
- */
-class OldExtraKeysConfigureFile(configureFile: File) : NeoConfigureFile(configureFile) {
- override var configVisitor: ConfigVisitor? = null
-
- override fun parseConfigure(): Boolean {
- try {
- val config = parseOldConfig(BufferedReader(FileReader(configureFile)))
- return generateVisitor(config)
- } catch (e: Exception) {
- NLog.e("ConfigureLoader", "Failed to load old extra keys config: ${e.localizedMessage}")
- return false
- }
- }
-
- private fun generateVisitor(config: NeoExtraKey): Boolean {
- configVisitor = ConfigVisitor()
- val visitor = configVisitor!!
- visitor.onStart()
- visitor.onEnterContext(NeoExtraKey.EKS_META_CONTEXT_NAME)
- visitor.getCurrentContext()
- .defineAttribute(NeoExtraKey.EKS_META_VERSION, NeoLangValue(config.version))
- .defineAttribute(NeoExtraKey.EKS_META_WITH_DEFAULT, NeoLangValue(config.withDefaultKeys))
-
- // program
- visitor.onEnterContext(NeoExtraKey.EKS_META_PROGRAM)
- config.programNames.forEachIndexed { index, program ->
- visitor.getCurrentContext().defineAttribute(index.toString(), NeoLangValue(program))
- }
- visitor.onExitContext()
-
- // key
- visitor.onEnterContext(NeoExtraKey.EKS_META_KEY)
- config.shortcutKeys.forEachIndexed { index, button ->
- if (button is TextButton) {
- visitor.onEnterContext(index.toString())
- visitor.getCurrentContext()
- .defineAttribute(NeoExtraKey.EKS_META_WITH_ENTER, NeoLangValue(button.withEnter))
- .defineAttribute(NeoExtraKey.EKS_META_DISPLAY, NeoLangValue(button.buttonKeys!!))
- .defineAttribute(NeoExtraKey.EKS_META_CODE, NeoLangValue(button.buttonKeys!!))
- visitor.onExitContext()
- }
- }
- visitor.onExitContext()
-
- visitor.onFinish()
- return true
- }
-
- private fun parseOldConfig(source: BufferedReader): NeoExtraKey {
- val config = NeoExtraKey()
- var line: String? = source.readLine()
-
- while (line != null) {
- line = line.trim().trimEnd()
- if (line.isEmpty() || line.startsWith("#")) {
- line = source.readLine()
- continue
- }
-
- if (line.startsWith(NeoExtraKey.EKS_META_VERSION)) {
- parseHeader(line, config)
- } else if (line.startsWith(NeoExtraKey.EKS_META_PROGRAM)) {
- parseProgram(line, config)
- } else if (line.startsWith("define")) {
- parseKeyDefine(line, config)
- } else if (line.startsWith(NeoExtraKey.EKS_META_WITH_DEFAULT)) {
- parseWithDefault(line, config)
- }
- line = source.readLine()
- }
-
- if (config.version < 0) {
- throw RuntimeException("Not a valid shortcut config file")
- }
- if (config.programNames.size == 0) {
- throw RuntimeException("At least one program name should be given")
- }
- return config
- }
-
- private fun parseWithDefault(line: String, config: NeoExtraKey) {
- val value = line.substring(NeoExtraKey.EKS_META_WITH_DEFAULT.length).trim().trimEnd()
- config.withDefaultKeys = value == "true"
- }
-
- private fun parseKeyDefine(line: String, config: NeoExtraKey) {
- val keyDefine = line.substring("define".length).trim().trimEnd()
- val keyValues = keyDefine.split(" ")
- if (keyValues.size < 2) {
- throw RuntimeException("Bad define")
- }
-
- val buttonText = keyValues[0]
- val withEnter = keyValues[1] == "true"
-
- config.shortcutKeys.add(TextButton(buttonText, withEnter))
- }
-
- private fun parseProgram(line: String, config: NeoExtraKey) {
- val programNames = line.substring(NeoExtraKey.EKS_META_PROGRAM.length).trim().trimEnd()
- if (programNames.isEmpty()) {
- return
- }
-
- for (name in programNames.split(" ")) {
- config.programNames.add(name)
- }
- }
-
- private fun parseHeader(line: String, config: NeoExtraKey) {
- val version: Int
- val versionString = line.substring(NeoExtraKey.EKS_META_VERSION.length).trim().trimEnd()
- try {
- version = Integer.parseInt(versionString)
- } catch (e: NumberFormatException) {
- throw RuntimeException("Bad version '$versionString'")
- }
-
- config.version = version
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedComponent.kt b/app/src/main/java/io/neoterm/component/data.kt
similarity index 88%
rename from app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedComponent.kt
rename to app/src/main/java/io/neoterm/component/data.kt
index 2bf248f..3dc2441 100644
--- a/app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedComponent.kt
+++ b/app/src/main/java/io/neoterm/component/data.kt
@@ -1,16 +1,16 @@
-package io.neoterm.frontend.component.helper
+package io.neoterm.component
import io.neolang.visitor.ConfigVisitor
import io.neoterm.component.config.ConfigureComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.component.NeoComponent
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.utils.NLog
import java.io.File
import java.io.FileFilter
-/**
- * @author kiva
- */
+interface ConfigFileBasedObject {
+ @Throws(RuntimeException::class)
+ fun onConfigLoaded(configVisitor: ConfigVisitor)
+}
+
abstract class ConfigFileBasedComponent(protected val baseDir: String) : NeoComponent {
companion object {
private val TAG = ConfigFileBasedComponent::class.java.simpleName
@@ -60,4 +60,5 @@ abstract class ConfigFileBasedComponent(protected
abstract fun onCheckComponentFiles()
abstract fun onCreateComponentObject(configVisitor: ConfigVisitor): T
-}
\ No newline at end of file
+}
+
diff --git a/app/src/main/java/io/neoterm/component/extrakey/ExtraKeyComponent.kt b/app/src/main/java/io/neoterm/component/extrakey/comp.kt
similarity index 87%
rename from app/src/main/java/io/neoterm/component/extrakey/ExtraKeyComponent.kt
rename to app/src/main/java/io/neoterm/component/extrakey/comp.kt
index 36ed3a7..93478d7 100644
--- a/app/src/main/java/io/neoterm/component/extrakey/ExtraKeyComponent.kt
+++ b/app/src/main/java/io/neoterm/component/extrakey/comp.kt
@@ -3,16 +3,13 @@ package io.neoterm.component.extrakey
import android.content.Context
import io.neolang.visitor.ConfigVisitor
import io.neoterm.App
-import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.ConfigFileBasedComponent
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
+import io.neoterm.utils.NLog
import io.neoterm.utils.extractAssetsDir
import java.io.File
-/**
- * @author kiva
- */
class ExtraKeyComponent : ConfigFileBasedComponent(NeoTermPath.EKS_PATH) {
override val checkComponentFileWhenObtained
get() = true
@@ -68,4 +65,4 @@ class ExtraKeyComponent : ConfigFileBasedComponent(NeoTermPath.EKS_
registerShortcutKeys(it)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/extrakey/NeoExtraKey.kt b/app/src/main/java/io/neoterm/component/extrakey/data.kt
similarity index 69%
rename from app/src/main/java/io/neoterm/component/extrakey/NeoExtraKey.kt
rename to app/src/main/java/io/neoterm/component/extrakey/data.kt
index 9eee948..df09a6f 100644
--- a/app/src/main/java/io/neoterm/component/extrakey/NeoExtraKey.kt
+++ b/app/src/main/java/io/neoterm/component/extrakey/data.kt
@@ -1,16 +1,10 @@
package io.neoterm.component.extrakey
import io.neolang.visitor.ConfigVisitor
-import io.neoterm.component.config.ConfigureComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.component.helper.ConfigFileBasedObject
-import io.neoterm.frontend.config.NeoConfigureFile
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
-import io.neoterm.frontend.terminal.extrakey.button.IExtraButton
-import io.neoterm.frontend.terminal.extrakey.button.TextButton
-import org.jetbrains.annotations.TestOnly
-import java.io.File
+import io.neoterm.component.ConfigFileBasedObject
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
+import io.neoterm.frontend.session.view.extrakey.IExtraButton
+import io.neoterm.frontend.session.view.extrakey.TextButton
/**
* @author kiva
@@ -86,24 +80,4 @@ class NeoExtraKey : ConfigFileBasedObject {
private fun getMetaByVisitor(visitor: ConfigVisitor, metaName: String): String? {
return visitor.getStringValue(EKS_META_CONTEXT_PATH, metaName)
}
-
- @TestOnly
- fun testLoadConfigure(file: File): Boolean {
- val loaderService = ComponentManager.getComponent()
-
- val configure: NeoConfigureFile?
- try {
- configure = loaderService.newLoader(file).loadConfigure()
- if (configure == null) {
- throw RuntimeException("Parse configuration failed.")
- }
- } catch (e: Exception) {
- NLog.e("ExtraKey", "Failed to load extra key config: ${file.absolutePath}: ${e.localizedMessage}")
- return false
- }
-
- val visitor = configure.getVisitor()
- onConfigLoaded(visitor)
- return true
- }
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/font/FontComponent.kt b/app/src/main/java/io/neoterm/component/font/comp.kt
similarity index 91%
rename from app/src/main/java/io/neoterm/component/font/FontComponent.kt
rename to app/src/main/java/io/neoterm/component/font/comp.kt
index 3c9d337..c22cf9c 100644
--- a/app/src/main/java/io/neoterm/component/font/FontComponent.kt
+++ b/app/src/main/java/io/neoterm/component/font/comp.kt
@@ -4,18 +4,15 @@ import android.content.Context
import android.graphics.Typeface
import io.neoterm.App
import io.neoterm.R
-import io.neoterm.frontend.component.NeoComponent
-import io.neoterm.frontend.config.DefaultValues
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.NeoComponent
+import io.neoterm.component.config.DefaultValues
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
import io.neoterm.utils.extractAssetsDir
import java.io.File
-/**
- * @author kiva
- */
class FontComponent : NeoComponent {
private lateinit var DEFAULT_FONT: NeoFont
private lateinit var fonts: MutableMap
@@ -126,4 +123,5 @@ class FontComponent : NeoComponent {
fonts.put(defaultFont, DEFAULT_FONT)
}
}
-}
\ No newline at end of file
+}
+
diff --git a/app/src/main/java/io/neoterm/component/font/NeoFont.kt b/app/src/main/java/io/neoterm/component/font/data.kt
similarity index 84%
rename from app/src/main/java/io/neoterm/component/font/NeoFont.kt
rename to app/src/main/java/io/neoterm/component/font/data.kt
index d4ac7fe..54f9815 100644
--- a/app/src/main/java/io/neoterm/component/font/NeoFont.kt
+++ b/app/src/main/java/io/neoterm/component/font/data.kt
@@ -1,13 +1,10 @@
package io.neoterm.component.font
import android.graphics.Typeface
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
import java.io.File
-/**
- * @author kiva
- */
class NeoFont {
private var fontFile: File? = null
private var typeface: Typeface? = null
@@ -36,4 +33,4 @@ class NeoFont {
}
return typeface
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/pm/Architecture.kt b/app/src/main/java/io/neoterm/component/pm/Architecture.kt
deleted file mode 100644
index b9ae753..0000000
--- a/app/src/main/java/io/neoterm/component/pm/Architecture.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package io.neoterm.component.pm
-
-/**
- * @author kiva
- */
-
-enum class Architecture {
- ALL, ARM, AARCH64, X86, X86_64;
-
- companion object {
- fun parse(arch: String): Architecture {
- return when (arch) {
- "arm" -> ARM
- "aarch64" -> AARCH64
- "x86" -> X86
- "x86_64" -> X86_64
- else -> ALL
- }
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/PackageComponent.java b/app/src/main/java/io/neoterm/component/pm/PackageComponent.java
index 0d10fc6..56099bd 100644
--- a/app/src/main/java/io/neoterm/component/pm/PackageComponent.java
+++ b/app/src/main/java/io/neoterm/component/pm/PackageComponent.java
@@ -1,6 +1,6 @@
package io.neoterm.component.pm;
-import io.neoterm.frontend.component.NeoComponent;
+import io.neoterm.component.NeoComponent;
import java.io.File;
import java.io.FileInputStream;
diff --git a/app/src/main/java/io/neoterm/component/pm/SourceManager.kt b/app/src/main/java/io/neoterm/component/pm/SourceManager.kt
deleted file mode 100644
index 1c398cc..0000000
--- a/app/src/main/java/io/neoterm/component/pm/SourceManager.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-package io.neoterm.component.pm
-
-import io.neoterm.App
-import io.neoterm.R
-import io.neoterm.framework.NeoTermDatabase
-import io.neoterm.frontend.config.NeoTermPath
-
-/**
- * @author kiva
- */
-class SourceManager internal constructor() {
- private val database = NeoTermDatabase.instance("sources")
-
- init {
- if (database.findAll(Source::class.java).isEmpty()) {
- App.get().resources.getStringArray(R.array.pref_package_source_values)
- .forEach {
- database.saveBean(Source(it, "stable main", true))
- }
- }
- }
-
- fun addSource(sourceUrl: String, repo: String, enabled: Boolean) {
- database.saveBean(Source(sourceUrl, repo, enabled))
- }
-
- fun removeSource(sourceUrl: String) {
- database.deleteBeanByWhere(Source::class.java, "url == '$sourceUrl'")
- }
-
- fun updateAll(sources: List) {
- database.dropAllTable()
- database.saveBeans(sources)
- }
-
- fun getAllSources(): List {
- return database.findAll(Source::class.java)
- }
-
- fun getEnabledSources(): List {
- return getAllSources().filter { it.enabled }
- }
-
- fun getMainPackageSource(): String {
- return getEnabledSources()
- .map { it.repo }
- .singleOrNull { it.trim() == "stable main" }
- ?: NeoTermPath.DEFAULT_MAIN_PACKAGE_SOURCE
- }
-
- fun applyChanges() {
- database.vacuum()
- }
-}
diff --git a/app/src/main/java/io/neoterm/component/pm/NeoPackageInfo.kt b/app/src/main/java/io/neoterm/component/pm/data.kt
similarity index 66%
rename from app/src/main/java/io/neoterm/component/pm/NeoPackageInfo.kt
rename to app/src/main/java/io/neoterm/component/pm/data.kt
index fa304a4..c7029c8 100644
--- a/app/src/main/java/io/neoterm/component/pm/NeoPackageInfo.kt
+++ b/app/src/main/java/io/neoterm/component/pm/data.kt
@@ -1,8 +1,20 @@
package io.neoterm.component.pm
-/**
- * @author kiva
- */
+enum class Architecture {
+ ALL, ARM, AARCH64, X86, X86_64;
+
+ companion object {
+ fun parse(arch: String): Architecture {
+ return when (arch) {
+ "arm" -> ARM
+ "aarch64" -> AARCH64
+ "x86" -> X86
+ "x86_64" -> X86_64
+ else -> ALL
+ }
+ }
+ }
+}
class NeoPackageInfo {
var packageName: String? = null
@@ -21,4 +33,3 @@ class NeoPackageInfo {
var homePage: String? = null
var description: String? = null
}
-
diff --git a/app/src/main/java/io/neoterm/component/pm/SourceHelper.kt b/app/src/main/java/io/neoterm/component/pm/helper.kt
similarity index 59%
rename from app/src/main/java/io/neoterm/component/pm/SourceHelper.kt
rename to app/src/main/java/io/neoterm/component/pm/helper.kt
index bf9b429..2b7ed9a 100644
--- a/app/src/main/java/io/neoterm/component/pm/SourceHelper.kt
+++ b/app/src/main/java/io/neoterm/component/pm/helper.kt
@@ -1,16 +1,16 @@
package io.neoterm.component.pm
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.App
+import io.neoterm.R
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.framework.NeoTermDatabase
+import io.neoterm.utils.NLog
import java.io.File
import java.net.URL
import java.nio.file.Files
import java.nio.file.Paths
-/**
- * @author kiva
- */
object SourceHelper {
fun syncSource() {
val sourceManager = ComponentManager.getComponent().sourceManager
@@ -71,4 +71,50 @@ object SourceHelper {
return ""
}
}
-}
\ No newline at end of file
+}
+
+class SourceManager internal constructor() {
+ private val database = NeoTermDatabase.instance("sources")
+
+ init {
+ if (database.findAll(Source::class.java).isEmpty()) {
+ App.get().resources.getStringArray(R.array.pref_package_source_values)
+ .forEach {
+ database.saveBean(Source(it, "stable main", true))
+ }
+ }
+ }
+
+ fun addSource(sourceUrl: String, repo: String, enabled: Boolean) {
+ database.saveBean(Source(sourceUrl, repo, enabled))
+ }
+
+ fun removeSource(sourceUrl: String) {
+ database.deleteBeanByWhere(Source::class.java, "url == '$sourceUrl'")
+ }
+
+ fun updateAll(sources: List) {
+ database.dropAllTable()
+ database.saveBeans(sources)
+ }
+
+ fun getAllSources(): List {
+ return database.findAll(Source::class.java)
+ }
+
+ fun getEnabledSources(): List {
+ return getAllSources().filter { it.enabled }
+ }
+
+ fun getMainPackageSource(): String {
+ return getEnabledSources()
+ .map { it.repo }
+ .singleOrNull { it.trim() == "stable main" }
+ ?: NeoTermPath.DEFAULT_MAIN_PACKAGE_SOURCE
+ }
+
+ fun applyChanges() {
+ database.vacuum()
+ }
+}
+
diff --git a/app/src/main/java/io/neoterm/component/profile/ProfileComponent.kt b/app/src/main/java/io/neoterm/component/profile/comp.kt
similarity index 90%
rename from app/src/main/java/io/neoterm/component/profile/ProfileComponent.kt
rename to app/src/main/java/io/neoterm/component/profile/comp.kt
index f362413..a283c22 100644
--- a/app/src/main/java/io/neoterm/component/profile/ProfileComponent.kt
+++ b/app/src/main/java/io/neoterm/component/profile/comp.kt
@@ -1,14 +1,11 @@
package io.neoterm.component.profile
import io.neolang.visitor.ConfigVisitor
-import io.neoterm.frontend.component.helper.ConfigFileBasedComponent
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.component.ConfigFileBasedComponent
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.utils.NLog
import java.io.File
-/**
- * @author kiva
- */
class ProfileComponent : ConfigFileBasedComponent(NeoTermPath.PROFILE_PATH) {
override val checkComponentFileWhenObtained
get() = true
@@ -63,4 +60,4 @@ class ProfileComponent : ConfigFileBasedComponent(NeoTermPath.PROFIL
fun unregisterProfile(metaName: String) {
profileRegistry.remove(metaName)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/profile/NeoProfile.kt b/app/src/main/java/io/neoterm/component/profile/data.kt
similarity index 81%
rename from app/src/main/java/io/neoterm/component/profile/NeoProfile.kt
rename to app/src/main/java/io/neoterm/component/profile/data.kt
index 88e21c4..4f53a06 100644
--- a/app/src/main/java/io/neoterm/component/profile/NeoProfile.kt
+++ b/app/src/main/java/io/neoterm/component/profile/data.kt
@@ -1,21 +1,18 @@
package io.neoterm.component.profile
import io.neolang.visitor.ConfigVisitor
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.ConfigFileBasedObject
+import io.neoterm.component.codegen.CodeGenObject
import io.neoterm.component.codegen.CodeGenParameter
-import io.neoterm.component.codegen.generators.NeoProfileGenerator
-import io.neoterm.component.codegen.interfaces.CodeGenObject
-import io.neoterm.component.codegen.interfaces.CodeGenerator
+import io.neoterm.component.codegen.CodeGenerator
+import io.neoterm.component.codegen.NeoProfileGenerator
import io.neoterm.component.config.ConfigureComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.component.helper.ConfigFileBasedObject
-import io.neoterm.frontend.config.NeoConfigureFile
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.component.config.NeoConfigureFile
+import io.neoterm.utils.NLog
import org.jetbrains.annotations.TestOnly
import java.io.File
-/**
- * @author kiva
- */
abstract class NeoProfile : CodeGenObject, ConfigFileBasedObject {
companion object {
private const val PROFILE_NAME = "name"
@@ -70,4 +67,4 @@ abstract class NeoProfile : CodeGenObject, ConfigFileBasedObject {
protected fun ConfigVisitor.getProfileBoolean(key: String): Boolean? {
return this.getBooleanValue(profileMetaPath, key)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/component/session/SessionComponent.kt b/app/src/main/java/io/neoterm/component/session/comp.kt
similarity index 85%
rename from app/src/main/java/io/neoterm/component/session/SessionComponent.kt
rename to app/src/main/java/io/neoterm/component/session/comp.kt
index 2fa9b89..9b08c38 100644
--- a/app/src/main/java/io/neoterm/component/session/SessionComponent.kt
+++ b/app/src/main/java/io/neoterm/component/session/comp.kt
@@ -4,18 +4,10 @@ import android.annotation.SuppressLint
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import io.neoterm.Globals
-import io.neoterm.frontend.component.NeoComponent
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.shell.ShellTermSession
-import io.neoterm.frontend.session.xorg.XParameter
-import io.neoterm.frontend.session.xorg.XSession
-import io.neoterm.frontend.session.xorg.client.XSessionData
+import io.neoterm.component.NeoComponent
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.utils.NLog
-/**
- * @author kiva
- */
class SessionComponent : NeoComponent {
companion object {
private var IS_LIBRARIES_LOADED = false
@@ -50,7 +42,7 @@ class SessionComponent : NeoComponent {
} catch (error: UnsatisfiedLinkError) {
NLog.e(
"SessionComponent", "Error loading lib " + soPath
- + ", reason: " + error.localizedMessage
+ + ", reason: " + error.localizedMessage
)
result = false
}
@@ -109,4 +101,4 @@ class SessionComponent : NeoComponent {
.profile(parameter.shellProfile)
.create(context)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt b/app/src/main/java/io/neoterm/component/session/shell.kt
similarity index 55%
rename from app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt
rename to app/src/main/java/io/neoterm/component/session/shell.kt
index 11e19b8..411b9b2 100644
--- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellTermSession.kt
+++ b/app/src/main/java/io/neoterm/component/session/shell.kt
@@ -1,13 +1,163 @@
-package io.neoterm.frontend.session.shell
+package io.neoterm.component.session
import android.content.Context
+import io.neolang.visitor.ConfigVisitor
import io.neoterm.App
import io.neoterm.R
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.session.shell.client.TermSessionCallback
+import io.neoterm.bridge.SessionId
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.colorscheme.ColorSchemeComponent
+import io.neoterm.component.config.DefaultValues
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.component.font.FontComponent
+import io.neoterm.component.profile.NeoProfile
+import io.neoterm.frontend.session.terminal.TermSessionCallback
import java.io.File
+/**
+ * @author kiva
+ */
+class ShellParameter {
+ var sessionId: SessionId? = null
+ var executablePath: String? = null
+ var arguments: Array? = null
+ var cwd: String? = null
+ var initialCommand: String? = null
+ var env: Array>? = null
+ var sessionCallback: TerminalSession.SessionChangedCallback? = null
+ var systemShell: Boolean = false
+ var shellProfile: ShellProfile? = null
+
+ fun executablePath(executablePath: String?): ShellParameter {
+ this.executablePath = executablePath
+ return this
+ }
+
+ fun arguments(arguments: Array?): ShellParameter {
+ this.arguments = arguments
+ return this
+ }
+
+ fun currentWorkingDirectory(cwd: String?): ShellParameter {
+ this.cwd = cwd
+ return this
+ }
+
+ fun initialCommand(initialCommand: String?): ShellParameter {
+ this.initialCommand = initialCommand
+ return this
+ }
+
+ fun environment(env: Array>?): ShellParameter {
+ this.env = env
+ return this
+ }
+
+ fun callback(callback: TerminalSession.SessionChangedCallback?): ShellParameter {
+ this.sessionCallback = callback
+ return this
+ }
+
+ fun systemShell(systemShell: Boolean): ShellParameter {
+ this.systemShell = systemShell
+ return this
+ }
+
+ fun profile(shellProfile: ShellProfile): ShellParameter {
+ this.shellProfile = shellProfile
+ return this
+ }
+
+ fun session(sessionId: SessionId?): ShellParameter {
+ this.sessionId = sessionId
+ return this
+ }
+
+ fun willCreateNewSession(): Boolean {
+ return sessionId?.equals(SessionId.NEW_SESSION) ?: true
+ }
+}
+
+/**
+ * @author kiva
+ */
+class ShellProfile : NeoProfile() {
+ companion object {
+ const val PROFILE_META_NAME = "profile-shell"
+
+ private const val LOGIN_SHELL = "login-shell"
+ private const val INITIAL_COMMAND = "init-command"
+ private const val BELL = "bell"
+ private const val VIBRATE = "vibrate"
+ private const val EXECVE_WRAPPER = "execve-wrapper"
+ private const val SPECIAL_VOLUME_KEYS = "special-volume-keys"
+ private const val AUTO_COMPLETION = "auto-completion"
+ private const val BACK_KEY_TO_ESC = "back-key-esc"
+ private const val EXTRA_KEYS = "extra-keys"
+ private const val FONT = "font"
+ private const val COLOR_SCHEME = "color-scheme"
+ private const val WORD_BASED_IME = "word-based-ime"
+
+ fun create(): ShellProfile {
+ return ShellProfile()
+ }
+ }
+
+ override val profileMetaName = PROFILE_META_NAME
+
+ var loginShell = DefaultValues.loginShell
+ var initialCommand = DefaultValues.initialCommand
+
+ var enableBell = DefaultValues.enableBell
+ var enableVibrate = DefaultValues.enableVibrate
+ var enableExecveWrapper = DefaultValues.enableExecveWrapper
+ var enableSpecialVolumeKeys = DefaultValues.enableSpecialVolumeKeys
+ var enableAutoCompletion = DefaultValues.enableAutoCompletion
+ var enableBackKeyToEscape = DefaultValues.enableBackButtonBeMappedToEscape
+ var enableExtraKeys = DefaultValues.enableExtraKeys
+ var enableWordBasedIme = DefaultValues.enableWordBasedIme
+
+ var profileFont: String
+ var profileColorScheme: String
+
+ init {
+ val fontComp = ComponentManager.getComponent()
+ val colorComp = ComponentManager.getComponent()
+
+ profileFont = fontComp.getCurrentFontName()
+ profileColorScheme = colorComp.getCurrentColorSchemeName()
+
+ loginShell = NeoPreference.getLoginShellPath()
+ initialCommand = NeoPreference.getInitialCommand()
+ enableBell = NeoPreference.isBellEnabled()
+ enableVibrate = NeoPreference.isVibrateEnabled()
+ enableExecveWrapper = NeoPreference.isExecveWrapperEnabled()
+ enableSpecialVolumeKeys = NeoPreference.isSpecialVolumeKeysEnabled()
+ enableAutoCompletion = NeoPreference.isAutoCompletionEnabled()
+ enableBackKeyToEscape = NeoPreference.isBackButtonBeMappedToEscapeEnabled()
+ enableExtraKeys = NeoPreference.isExtraKeysEnabled()
+ enableWordBasedIme = NeoPreference.isWordBasedImeEnabled()
+ }
+
+ override fun onConfigLoaded(configVisitor: ConfigVisitor) {
+ super.onConfigLoaded(configVisitor)
+ loginShell = configVisitor.getProfileString(LOGIN_SHELL, loginShell)
+ initialCommand = configVisitor.getProfileString(INITIAL_COMMAND, initialCommand)
+ enableBell = configVisitor.getProfileBoolean(BELL, enableBell)
+ enableVibrate = configVisitor.getProfileBoolean(VIBRATE, enableVibrate)
+ enableExecveWrapper = configVisitor.getProfileBoolean(EXECVE_WRAPPER, enableExecveWrapper)
+ enableSpecialVolumeKeys = configVisitor.getProfileBoolean(SPECIAL_VOLUME_KEYS, enableSpecialVolumeKeys)
+ enableAutoCompletion = configVisitor.getProfileBoolean(AUTO_COMPLETION, enableAutoCompletion)
+ enableBackKeyToEscape = configVisitor.getProfileBoolean(BACK_KEY_TO_ESC, enableBackKeyToEscape)
+ enableExtraKeys = configVisitor.getProfileBoolean(EXTRA_KEYS, enableExtraKeys)
+ enableWordBasedIme = configVisitor.getProfileBoolean(WORD_BASED_IME, enableWordBasedIme)
+ profileFont = configVisitor.getProfileString(FONT, profileFont)
+ profileColorScheme = configVisitor.getProfileString(COLOR_SCHEME, profileColorScheme)
+ }
+}
+
/**
* @author kiva
*/
@@ -244,4 +394,4 @@ open class ShellTermSession private constructor(
return "${NeoTermPath.USR_PATH}/bin:${NeoTermPath.USR_PATH}/bin/applets"
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/session/xorg/XSession.kt b/app/src/main/java/io/neoterm/component/session/x.kt
similarity index 95%
rename from app/src/main/java/io/neoterm/frontend/session/xorg/XSession.kt
rename to app/src/main/java/io/neoterm/component/session/x.kt
index 3794dcf..62e4595 100644
--- a/app/src/main/java/io/neoterm/frontend/session/xorg/XSession.kt
+++ b/app/src/main/java/io/neoterm/component/session/x.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.session.xorg
+package io.neoterm.component.session
import android.app.UiModeManager
import android.content.Context
@@ -7,6 +7,7 @@ import android.content.pm.PackageManager
import android.content.res.Configuration
import android.inputmethodservice.Keyboard
import android.inputmethodservice.KeyboardView
+import android.os.Build
import android.os.SystemClock
import android.text.InputType
import android.view.*
@@ -15,14 +16,11 @@ import android.widget.EditText
import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity
import io.neoterm.*
-import io.neoterm.frontend.session.xorg.client.XSessionData
import io.neoterm.xorg.NeoXorgViewClient
import io.neoterm.xorg.R
import java.util.*
-/**
- * @author kiva
- */
+class XParameter
class XSession constructor(private val mActivity: AppCompatActivity, val mSessionData: XSessionData) :
NeoXorgViewClient {
@@ -64,17 +62,11 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
}
override fun getContext() = mActivity
-
override fun isKeyboardWithoutTextInputShown() = mSessionData.keyboardWithoutTextInputShown
-
override fun isPaused() = mSessionData.isPaused
-
override fun runOnUiThread(runnable: Runnable?) = mActivity.runOnUiThread(runnable)
-
override fun getGLView() = mSessionData.glView
-
override fun getWindow() = mActivity.window!!
-
override fun getWindowManager() = mActivity.windowManager!!
override fun showScreenKeyboardWithoutTextInputField(keyboard: Int) {
@@ -244,7 +236,7 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
val screenKeyboard = EditText(
mActivity, null,
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
android.R.style.TextAppearance_Material_Widget_EditText
else android.R.style.TextAppearance_Widget_EditText
)
@@ -349,10 +341,10 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
override fun setSystemMousePointerVisible(visible: Int) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
- glView?.pointerIcon = android.view.PointerIcon.getSystemIcon(
+ glView?.pointerIcon = PointerIcon.getSystemIcon(
mActivity,
- if (visible == 0) android.view.PointerIcon.TYPE_NULL
- else android.view.PointerIcon.TYPE_DEFAULT
+ if (visible == 0) PointerIcon.TYPE_NULL
+ else PointerIcon.TYPE_DEFAULT
)
}
}
@@ -417,5 +409,18 @@ class XSession constructor(private val mActivity: AppCompatActivity, val mSessio
}
}
}
-
+}
+
+class XSessionData {
+ var videoLayout: FrameLayout? = null
+ var audioThread: NeoAudioThread? = null
+ var screenKeyboard: View? = null
+ var glView: NeoGLView? = null
+
+ var isPaused = false
+ var client: NeoXorgViewClient? = null
+
+ var keyboardWithoutTextInputShown = false
+ var screenKeyboardHintMessage: String? = null
+ var textInput = LinkedList()
}
diff --git a/app/src/main/java/io/neoterm/component/userscript/UserScript.kt b/app/src/main/java/io/neoterm/component/userscript/UserScript.kt
deleted file mode 100644
index 8d677ac..0000000
--- a/app/src/main/java/io/neoterm/component/userscript/UserScript.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.neoterm.component.userscript
-
-import java.io.File
-
-/**
- * @author kiva
- */
-class UserScript(val scriptFile: File)
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/component/userscript/UserScriptComponent.kt b/app/src/main/java/io/neoterm/component/userscript/comp.kt
similarity index 83%
rename from app/src/main/java/io/neoterm/component/userscript/UserScriptComponent.kt
rename to app/src/main/java/io/neoterm/component/userscript/comp.kt
index 5cf90ba..4378972 100644
--- a/app/src/main/java/io/neoterm/component/userscript/UserScriptComponent.kt
+++ b/app/src/main/java/io/neoterm/component/userscript/comp.kt
@@ -3,17 +3,16 @@ package io.neoterm.component.userscript
import android.content.Context
import android.system.Os
import io.neoterm.App
-import io.neoterm.frontend.component.NeoComponent
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.logging.NLog
+import io.neoterm.component.NeoComponent
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.utils.NLog
import io.neoterm.utils.extractAssetsDir
import java.io.File
-/**
- * @author kiva
- */
+class UserScript(val scriptFile: File)
+
class UserScriptComponent : NeoComponent {
- private var userScripts = listOf()
+ var userScripts = listOf()
private val scriptDir = File(NeoTermPath.USER_SCRIPT_PATH)
override fun onServiceInit() = checkForFiles()
diff --git a/app/src/main/java/io/neoterm/framework/NeoTermDatabase.java b/app/src/main/java/io/neoterm/framework/NeoTermDatabase.java
index a512db4..70d73ee 100644
--- a/app/src/main/java/io/neoterm/framework/NeoTermDatabase.java
+++ b/app/src/main/java/io/neoterm/framework/NeoTermDatabase.java
@@ -9,7 +9,7 @@ import io.neoterm.App;
import io.neoterm.framework.database.*;
import io.neoterm.framework.database.bean.TableInfo;
import io.neoterm.framework.reflection.Reflect;
-import io.neoterm.frontend.logging.NLog;
+import io.neoterm.utils.NLog;
import java.io.File;
import java.io.IOException;
diff --git a/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt b/app/src/main/java/io/neoterm/frontend/completion/CandidatePopupWindow.kt
similarity index 90%
rename from app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt
rename to app/src/main/java/io/neoterm/frontend/completion/CandidatePopupWindow.kt
index 3c06157..d14d543 100644
--- a/app/src/main/java/io/neoterm/frontend/completion/view/CandidatePopupWindow.kt
+++ b/app/src/main/java/io/neoterm/frontend/completion/CandidatePopupWindow.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.completion.view
+package io.neoterm.frontend.completion
import android.content.Context
import android.view.Gravity
@@ -11,11 +11,11 @@ import android.widget.PopupWindow
import android.widget.TextView
import io.neoterm.R
import io.neoterm.backend.TerminalColors
+import io.neoterm.component.ComponentManager
import io.neoterm.component.colorscheme.ColorSchemeComponent
-import io.neoterm.frontend.completion.listener.OnCandidateSelectedListener
-import io.neoterm.frontend.completion.model.CompletionCandidate
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.terminal.TerminalView
+import io.neoterm.component.completion.CompletionCandidate
+import io.neoterm.component.completion.OnCandidateSelectedListener
+import io.neoterm.frontend.session.view.TerminalView
/**
* @author kiva
@@ -41,14 +41,13 @@ class CandidatePopupWindow(val context: Context) {
// Ensure that the popup window will not cover the IME.
val rootView = popWindow.contentView
if (rootView is MaxHeightView) {
- val maxHeight = terminalView.height
- rootView.setMaxHeight(maxHeight)
+ rootView.maxHeight = terminalView.height
}
popWindow.showAtLocation(
terminalView, Gravity.BOTTOM.and(Gravity.START),
terminalView.cursorAbsoluteX,
- terminalView.cursorAbsoluteY
+ terminalView.cursorAbsoluteY,
)
}
}
@@ -69,12 +68,12 @@ class CandidatePopupWindow(val context: Context) {
val listView = contentView.findViewById(R.id.popup_complete_candidate_list)
candidateAdapter = CandidateAdapter(this)
listView.adapter = candidateAdapter
- listView.setOnItemClickListener({ _, _, position, _ ->
+ listView.setOnItemClickListener { _, _, position, _ ->
val selectedItem = candidates?.get(position)
if (selectedItem != null) {
onCandidateSelectedListener?.onCandidateSelected(selectedItem)
}
- })
+ }
candidateListView = listView
popupWindow.contentView = contentView
@@ -143,4 +142,4 @@ class CandidatePopupWindow(val context: Context) {
description.setTextColor(textColor)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/completion/view/MaxHeightView.kt b/app/src/main/java/io/neoterm/frontend/completion/MaxHeightView.kt
similarity index 82%
rename from app/src/main/java/io/neoterm/frontend/completion/view/MaxHeightView.kt
rename to app/src/main/java/io/neoterm/frontend/completion/MaxHeightView.kt
index 49a0356..e4c8049 100644
--- a/app/src/main/java/io/neoterm/frontend/completion/view/MaxHeightView.kt
+++ b/app/src/main/java/io/neoterm/frontend/completion/MaxHeightView.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.completion.view
+package io.neoterm.frontend.completion
import android.content.Context
import android.util.AttributeSet
@@ -6,18 +6,11 @@ import android.view.View
import android.widget.LinearLayout
class MaxHeightView : LinearLayout {
+ var maxHeight = -1
- private var maxHeight = -1
-
- constructor(context: Context) : super(context) {}
-
- constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}
-
- constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}
-
- fun setMaxHeight(maxHeight: Int) {
- this.maxHeight = maxHeight
- }
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
+ constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var finalHeightMeasureSpec = heightMeasureSpec
@@ -53,4 +46,4 @@ class MaxHeightView : LinearLayout {
super.onMeasure(widthMeasureSpec, finalHeightMeasureSpec)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/completion/ProviderDetector.kt b/app/src/main/java/io/neoterm/frontend/completion/ProviderDetector.kt
deleted file mode 100644
index 9bc9268..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/ProviderDetector.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.neoterm.frontend.completion
-
-import io.neoterm.frontend.completion.listener.MarkScoreListener
-import io.neoterm.frontend.completion.provider.ICandidateProvider
-
-/**
- * @author kiva
- */
-class ProviderDetector(val providers: List) : MarkScoreListener {
- private var detectedProvider: ICandidateProvider? = null
-
- override fun onMarkScore(score: Int) {
- // TODO: Save provider score
- }
-
- fun detectBest(): ICandidateProvider? {
- // TODO: detect best
- detectedProvider = if (providers.isEmpty())
- null
- else
- providers[0]
-
- return detectedProvider
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/completion/listener/MarkScoreListener.kt b/app/src/main/java/io/neoterm/frontend/completion/listener/MarkScoreListener.kt
deleted file mode 100644
index 2e8c1d2..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/listener/MarkScoreListener.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.neoterm.frontend.completion.listener
-
-/**
- * @author kiva
- */
-
-interface MarkScoreListener {
- fun onMarkScore(score: Int)
-}
diff --git a/app/src/main/java/io/neoterm/frontend/completion/listener/OnAutoCompleteListener.kt b/app/src/main/java/io/neoterm/frontend/completion/listener/OnAutoCompleteListener.kt
deleted file mode 100755
index feb7c8e..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/listener/OnAutoCompleteListener.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package io.neoterm.frontend.completion.listener
-
-/**
- * @author Kiva
- * *
- * @version 1.0
- */
-interface OnAutoCompleteListener {
- fun onCompletionRequired(newText: String?)
-
- fun onKeyCode(keyCode: Int, keyMod: Int)
-
- fun onCleanUp()
-
- fun onFinishCompletion(): Boolean
-}
diff --git a/app/src/main/java/io/neoterm/frontend/completion/listener/OnCandidateSelectedListener.kt b/app/src/main/java/io/neoterm/frontend/completion/listener/OnCandidateSelectedListener.kt
deleted file mode 100644
index 89644f4..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/listener/OnCandidateSelectedListener.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.frontend.completion.listener
-
-import io.neoterm.frontend.completion.model.CompletionCandidate
-
-/**
- * @author kiva
- */
-interface OnCandidateSelectedListener {
- fun onCandidateSelected(candidate: CompletionCandidate)
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/completion/model/CompletionCandidate.kt b/app/src/main/java/io/neoterm/frontend/completion/model/CompletionCandidate.kt
deleted file mode 100644
index e819a26..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/model/CompletionCandidate.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.neoterm.frontend.completion.model
-
-/**
- * @author kiva
- */
-class CompletionCandidate(var completeString: String) {
- var displayName: String = completeString
- var description: String? = null
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/completion/provider/ICandidateProvider.kt b/app/src/main/java/io/neoterm/frontend/completion/provider/ICandidateProvider.kt
deleted file mode 100644
index e3a39b7..0000000
--- a/app/src/main/java/io/neoterm/frontend/completion/provider/ICandidateProvider.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.neoterm.frontend.completion.provider
-
-import io.neoterm.frontend.completion.model.CompletionCandidate
-
-/**
- * @author kiva
- */
-
-interface ICandidateProvider {
- val providerName: String
-
- fun provideCandidates(text: String): List?
-
- fun canComplete(text: String): Boolean
-}
diff --git a/app/src/main/java/io/neoterm/frontend/component/ComponentDuplicateException.kt b/app/src/main/java/io/neoterm/frontend/component/ComponentDuplicateException.kt
deleted file mode 100644
index a47c5ab..0000000
--- a/app/src/main/java/io/neoterm/frontend/component/ComponentDuplicateException.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.component
-
-/**
- * @author kiva
- */
-class ComponentDuplicateException(serviceName: String) : RuntimeException("Service $serviceName duplicate")
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/component/ComponentNotFoundException.kt b/app/src/main/java/io/neoterm/frontend/component/ComponentNotFoundException.kt
deleted file mode 100644
index d7289ce..0000000
--- a/app/src/main/java/io/neoterm/frontend/component/ComponentNotFoundException.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.neoterm.frontend.component
-
-/**
- * @author kiva
- */
-class ComponentNotFoundException(serviceName: String) : RuntimeException("Component `$serviceName' not found") {
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/component/NeoComponent.kt b/app/src/main/java/io/neoterm/frontend/component/NeoComponent.kt
deleted file mode 100644
index f54c6d3..0000000
--- a/app/src/main/java/io/neoterm/frontend/component/NeoComponent.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.frontend.component
-
-/**
- * @author kiva
- */
-interface NeoComponent {
- fun onServiceInit()
- fun onServiceDestroy()
- fun onServiceObtained()
-}
diff --git a/app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedObject.kt b/app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedObject.kt
deleted file mode 100644
index 69cbd83..0000000
--- a/app/src/main/java/io/neoterm/frontend/component/helper/ConfigFileBasedObject.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package io.neoterm.frontend.component.helper
-
-import io.neolang.visitor.ConfigVisitor
-
-/**
- * @author kiva
- */
-interface ConfigFileBasedObject {
- @Throws(RuntimeException::class)
- fun onConfigLoaded(configVisitor: ConfigVisitor)
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt b/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt
deleted file mode 100644
index 4236d7c..0000000
--- a/app/src/main/java/io/neoterm/frontend/config/DefaultValues.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.neoterm.frontend.config
-
-/**
- * @author kiva
- */
-object DefaultValues {
- const val fontSize = 30
-
- const val enableBell = false
- const val enableVibrate = false
- const val enableExecveWrapper = true
- const val enableAutoCompletion = false
- const val enableFullScreen = false
- const val enableAutoHideToolbar = false
- const val enableSwitchNextTab = false
- const val enableExtraKeys = true
- const val enableExplicitExtraKeysWeight = false
- const val enableBackButtonBeMappedToEscape = false
- const val enableSpecialVolumeKeys = false
- const val enableWordBasedIme = false
-
- const val loginShell = "bash"
- const val initialCommand = ""
- const val defaultFont = "SourceCodePro"
-}
diff --git a/app/src/main/java/io/neoterm/frontend/config/NeoConfigureFile.kt b/app/src/main/java/io/neoterm/frontend/config/NeoConfigureFile.kt
deleted file mode 100644
index e0b0651..0000000
--- a/app/src/main/java/io/neoterm/frontend/config/NeoConfigureFile.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.neoterm.frontend.config
-
-import io.neolang.parser.NeoLangParser
-import io.neolang.visitor.ConfigVisitor
-import java.io.File
-import java.nio.file.Files
-
-/**
- * @author kiva
- */
-open class NeoConfigureFile(val configureFile: File) {
- private val configParser = NeoLangParser()
- open protected var configVisitor: ConfigVisitor? = null
-
- fun getVisitor() = configVisitor ?: throw IllegalStateException("Configure file not loaded or parse failed.")
-
- open fun parseConfigure() = kotlin.runCatching {
- val programCode = String(Files.readAllBytes(configureFile.toPath()))
- configParser.setInputSource(programCode)
-
- val ast = configParser.parse()
- val astVisitor = ast.visit().getVisitor(ConfigVisitor::class.java) ?: return false
- astVisitor.start()
- configVisitor = astVisitor.getCallback()
- }.isSuccess
-}
diff --git a/app/src/main/java/io/neoterm/frontend/floating/WindowTermView.kt b/app/src/main/java/io/neoterm/frontend/floating/WindowTermView.kt
deleted file mode 100644
index b05b835..0000000
--- a/app/src/main/java/io/neoterm/frontend/floating/WindowTermView.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.neoterm.frontend.floating
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.View
-import io.neoterm.R
-import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.TerminalViewClient
-import io.neoterm.utils.Terminals
-
-/**
- * @author kiva
- */
-class WindowTermView(val context: Context) {
- @SuppressLint("InflateParams")
- var rootView: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
- private set
- var terminalView: TerminalView = rootView.findViewById(R.id.terminal_view_dialog)
- private set
-
- init {
- Terminals.setupTerminalView(terminalView)
- }
-
- fun setTerminalViewClient(terminalViewClient: TerminalViewClient?) {
- terminalView.setTerminalViewClient(terminalViewClient)
- }
-
- fun attachSession(terminalSession: TerminalSession?) {
- terminalView.attachSession(terminalSession)
- }
-
- fun setInputMethodEnabled(enabled: Boolean) {
- terminalView.isFocusable = enabled
- terminalView.isFocusableInTouchMode = enabled
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/floating/TerminalDialog.kt b/app/src/main/java/io/neoterm/frontend/floating/dialog.kt
similarity index 69%
rename from app/src/main/java/io/neoterm/frontend/floating/TerminalDialog.kt
rename to app/src/main/java/io/neoterm/frontend/floating/dialog.kt
index a62bf20..864ad30 100644
--- a/app/src/main/java/io/neoterm/frontend/floating/TerminalDialog.kt
+++ b/app/src/main/java/io/neoterm/frontend/floating/dialog.kt
@@ -1,21 +1,23 @@
package io.neoterm.frontend.floating
+import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
+import android.view.LayoutInflater
+import android.view.View
import androidx.appcompat.app.AlertDialog
import io.neoterm.R
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.shell.ShellTermSession
-import io.neoterm.frontend.session.shell.client.BasicSessionCallback
-import io.neoterm.frontend.session.shell.client.BasicViewClient
+import io.neoterm.component.session.ShellParameter
+import io.neoterm.component.session.ShellTermSession
+import io.neoterm.frontend.session.terminal.BasicSessionCallback
+import io.neoterm.frontend.session.terminal.BasicViewClient
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.TerminalViewClient
import io.neoterm.utils.Terminals
typealias DialogSessionFinished = (TerminalDialog, TerminalSession?) -> Unit
-/**
- * @author kiva
- */
class TerminalDialog(val context: Context) {
private val termWindowView = WindowTermView(context)
private val terminalSessionCallback: BasicSessionCallback
@@ -92,4 +94,29 @@ class TerminalDialog(val context: Context) {
}
return this
}
-}
\ No newline at end of file
+}
+
+class WindowTermView(val context: Context) {
+ @SuppressLint("InflateParams")
+ var rootView: View = LayoutInflater.from(context).inflate(R.layout.ui_term_dialog, null, false)
+ private set
+ var terminalView: TerminalView = rootView.findViewById(R.id.terminal_view_dialog)
+ private set
+
+ init {
+ Terminals.setupTerminalView(terminalView)
+ }
+
+ fun setTerminalViewClient(terminalViewClient: TerminalViewClient?) {
+ terminalView.setTerminalViewClient(terminalViewClient)
+ }
+
+ fun attachSession(terminalSession: TerminalSession?) {
+ terminalView.attachSession(terminalSession)
+ }
+
+ fun setInputMethodEnabled(enabled: Boolean) {
+ terminalView.isFocusable = enabled
+ terminalView.isFocusableInTouchMode = enabled
+ }
+}
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt b/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt
deleted file mode 100644
index ff7f37f..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellParameter.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package io.neoterm.frontend.session.shell
-
-import io.neoterm.backend.TerminalSession
-import io.neoterm.bridge.SessionId
-
-/**
- * @author kiva
- */
-class ShellParameter {
- var sessionId: SessionId? = null
- var executablePath: String? = null
- var arguments: Array? = null
- var cwd: String? = null
- var initialCommand: String? = null
- var env: Array>? = null
- var sessionCallback: TerminalSession.SessionChangedCallback? = null
- var systemShell: Boolean = false
- var shellProfile: ShellProfile? = null
-
- fun executablePath(executablePath: String?): ShellParameter {
- this.executablePath = executablePath
- return this
- }
-
- fun arguments(arguments: Array?): ShellParameter {
- this.arguments = arguments
- return this
- }
-
- fun currentWorkingDirectory(cwd: String?): ShellParameter {
- this.cwd = cwd
- return this
- }
-
- fun initialCommand(initialCommand: String?): ShellParameter {
- this.initialCommand = initialCommand
- return this
- }
-
- fun environment(env: Array>?): ShellParameter {
- this.env = env
- return this
- }
-
- fun callback(callback: TerminalSession.SessionChangedCallback?): ShellParameter {
- this.sessionCallback = callback
- return this
- }
-
- fun systemShell(systemShell: Boolean): ShellParameter {
- this.systemShell = systemShell
- return this
- }
-
- fun profile(shellProfile: ShellProfile): ShellParameter {
- this.shellProfile = shellProfile
- return this
- }
-
- fun session(sessionId: SessionId?): ShellParameter {
- this.sessionId = sessionId
- return this
- }
-
- fun willCreateNewSession(): Boolean {
- return sessionId?.equals(SessionId.NEW_SESSION) ?: true
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt b/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt
deleted file mode 100644
index 8f2bf0d..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/ShellProfile.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-package io.neoterm.frontend.session.shell
-
-import io.neolang.visitor.ConfigVisitor
-import io.neoterm.component.colorscheme.ColorSchemeComponent
-import io.neoterm.component.font.FontComponent
-import io.neoterm.component.profile.NeoProfile
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.DefaultValues
-import io.neoterm.frontend.config.NeoPreference
-
-/**
- * @author kiva
- */
-class ShellProfile : NeoProfile() {
- companion object {
- const val PROFILE_META_NAME = "profile-shell"
-
- private const val LOGIN_SHELL = "login-shell"
- private const val INITIAL_COMMAND = "init-command"
- private const val BELL = "bell"
- private const val VIBRATE = "vibrate"
- private const val EXECVE_WRAPPER = "execve-wrapper"
- private const val SPECIAL_VOLUME_KEYS = "special-volume-keys"
- private const val AUTO_COMPLETION = "auto-completion"
- private const val BACK_KEY_TO_ESC = "back-key-esc"
- private const val EXTRA_KEYS = "extra-keys"
- private const val FONT = "font"
- private const val COLOR_SCHEME = "color-scheme"
- private const val WORD_BASED_IME = "word-based-ime"
-
- fun create(): ShellProfile {
- return ShellProfile()
- }
- }
-
- override val profileMetaName = PROFILE_META_NAME
-
- var loginShell = DefaultValues.loginShell
- var initialCommand = DefaultValues.initialCommand
-
- var enableBell = DefaultValues.enableBell
- var enableVibrate = DefaultValues.enableVibrate
- var enableExecveWrapper = DefaultValues.enableExecveWrapper
- var enableSpecialVolumeKeys = DefaultValues.enableSpecialVolumeKeys
- var enableAutoCompletion = DefaultValues.enableAutoCompletion
- var enableBackKeyToEscape = DefaultValues.enableBackButtonBeMappedToEscape
- var enableExtraKeys = DefaultValues.enableExtraKeys
- var enableWordBasedIme = DefaultValues.enableWordBasedIme
-
- var profileFont: String
- var profileColorScheme: String
-
- init {
- val fontComp = ComponentManager.getComponent()
- val colorComp = ComponentManager.getComponent()
-
- profileFont = fontComp.getCurrentFontName()
- profileColorScheme = colorComp.getCurrentColorSchemeName()
-
- loginShell = NeoPreference.getLoginShellPath()
- initialCommand = NeoPreference.getInitialCommand()
- enableBell = NeoPreference.isBellEnabled()
- enableVibrate = NeoPreference.isVibrateEnabled()
- enableExecveWrapper = NeoPreference.isExecveWrapperEnabled()
- enableSpecialVolumeKeys = NeoPreference.isSpecialVolumeKeysEnabled()
- enableAutoCompletion = NeoPreference.isAutoCompletionEnabled()
- enableBackKeyToEscape = NeoPreference.isBackButtonBeMappedToEscapeEnabled()
- enableExtraKeys = NeoPreference.isExtraKeysEnabled()
- enableWordBasedIme = NeoPreference.isWordBasedImeEnabled()
- }
-
- override fun onConfigLoaded(configVisitor: ConfigVisitor) {
- super.onConfigLoaded(configVisitor)
- loginShell = configVisitor.getProfileString(LOGIN_SHELL, loginShell)
- initialCommand = configVisitor.getProfileString(INITIAL_COMMAND, initialCommand)
- enableBell = configVisitor.getProfileBoolean(BELL, enableBell)
- enableVibrate = configVisitor.getProfileBoolean(VIBRATE, enableVibrate)
- enableExecveWrapper = configVisitor.getProfileBoolean(EXECVE_WRAPPER, enableExecveWrapper)
- enableSpecialVolumeKeys = configVisitor.getProfileBoolean(SPECIAL_VOLUME_KEYS, enableSpecialVolumeKeys)
- enableAutoCompletion = configVisitor.getProfileBoolean(AUTO_COMPLETION, enableAutoCompletion)
- enableBackKeyToEscape = configVisitor.getProfileBoolean(BACK_KEY_TO_ESC, enableBackKeyToEscape)
- enableExtraKeys = configVisitor.getProfileBoolean(EXTRA_KEYS, enableExtraKeys)
- enableWordBasedIme = configVisitor.getProfileBoolean(WORD_BASED_IME, enableWordBasedIme)
- profileFont = configVisitor.getProfileString(FONT, profileFont)
- profileColorScheme = configVisitor.getProfileString(COLOR_SCHEME, profileColorScheme)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/BasicSessionCallback.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/BasicSessionCallback.kt
deleted file mode 100644
index d0bfdb4..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/BasicSessionCallback.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package io.neoterm.frontend.session.shell.client
-
-import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.terminal.TerminalView
-
-/**
- * @author kiva
- */
-open class BasicSessionCallback(var terminalView: TerminalView) : TerminalSession.SessionChangedCallback {
- override fun onTextChanged(changedSession: TerminalSession?) {
- if (changedSession != null) {
- terminalView.onScreenUpdated()
- }
- }
-
- override fun onTitleChanged(changedSession: TerminalSession?) {
- }
-
- override fun onSessionFinished(finishedSession: TerminalSession?) {
- }
-
- override fun onClipboardText(session: TerminalSession?, text: String?) {
- }
-
- override fun onBell(session: TerminalSession?) {
- }
-
- override fun onColorsChanged(session: TerminalSession?) {
- if (session != null) {
- terminalView.onScreenUpdated()
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/BellController.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/BellController.kt
deleted file mode 100644
index 57e01ab..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/BellController.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-package io.neoterm.frontend.session.shell.client
-
-import android.content.Context
-import android.media.SoundPool
-import android.os.Vibrator
-import io.neoterm.R
-import io.neoterm.frontend.session.shell.ShellTermSession
-
-/**
- * @author kiva
- */
-class BellController constructor() {
- companion object {
- private val BELL_DELAY_MS = 100
- }
-
- private var bellId: Int = 0
- private var soundPool: SoundPool? = null
- private var lastBellTime = 0L
-
- fun bellOrVibrate(context: Context, session: ShellTermSession) {
- val currentTime = System.currentTimeMillis()
- if (currentTime - lastBellTime < BELL_DELAY_MS) {
- return
- }
- lastBellTime = currentTime
-
- if (session.shellProfile.enableBell) {
- if (soundPool == null) {
- soundPool = SoundPool.Builder().setMaxStreams(1).build()
- bellId = soundPool!!.load(context, R.raw.bell, 1)
- }
- soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
- }
-
- if (session.shellProfile.enableVibrate) {
- val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
- vibrator.vibrate(100)
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermCompleteListener.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermCompleteListener.kt
deleted file mode 100644
index 538d4c3..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermCompleteListener.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-package io.neoterm.frontend.session.shell.client
-
-import android.util.Log
-import android.view.KeyEvent
-import io.neoterm.BuildConfig
-import io.neoterm.frontend.completion.CompletionManager
-import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
-import io.neoterm.frontend.completion.listener.OnCandidateSelectedListener
-import io.neoterm.frontend.completion.model.CompletionCandidate
-import io.neoterm.frontend.completion.model.CompletionResult
-import io.neoterm.frontend.completion.view.CandidatePopupWindow
-import io.neoterm.frontend.terminal.TerminalView
-import java.util.*
-
-/**
- * @author kiva
- */
-class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteListener, OnCandidateSelectedListener {
- private val inputStack = Stack()
- private var popupWindow: CandidatePopupWindow? = null
- private var lastCompletedIndex = 0
-
- override fun onKeyCode(keyCode: Int, keyMod: Int) {
- when (keyCode) {
- KeyEvent.KEYCODE_DEL -> {
- popChar()
- fixLastCompletedIndex()
- triggerCompletion()
- }
-
- KeyEvent.KEYCODE_ENTER -> {
- clearChars()
- popupWindow?.dismiss()
- }
- }
- }
-
- private fun fixLastCompletedIndex() {
- val currentText = getCurrentEditingText()
- lastCompletedIndex = minOf(lastCompletedIndex, currentText.length - 1)
- }
-
- override fun onCompletionRequired(newText: String?) {
- if (newText == null || newText.isEmpty()) {
- return
- }
- pushString(newText)
- triggerCompletion()
- }
-
- override fun onCleanUp() {
- popupWindow?.dismiss()
- popupWindow?.cleanup()
- popupWindow = null
- terminalView = null
- }
-
- override fun onFinishCompletion(): Boolean {
- val popWindow = popupWindow ?: return false
-
- if (popWindow.isShowing()) {
- popWindow.dismiss()
- return true
- }
- return false
- }
-
- override fun onCandidateSelected(candidate: CompletionCandidate) {
- val session = terminalView?.currentSession ?: return
- val textNeedCompletion = getCurrentEditingText().substring(lastCompletedIndex + 1)
- val newText = candidate.completeString
-
- val deleteLength = newText.indexOf(textNeedCompletion) + textNeedCompletion.length
- if (deleteLength > 0) {
- for (i in 0 until deleteLength) {
- session.write("\b")
- popChar()
- }
- }
-
- if (BuildConfig.DEBUG) {
- Log.e(
- "NeoTerm-AC", "currentEditing: $textNeedCompletion, " +
- "deleteLength: $deleteLength, completeString: $newText"
- )
- }
-
- pushString(newText)
- session.write(newText)
- // Trigger next completion
- lastCompletedIndex = inputStack.size
- triggerCompletion()
- }
-
- private fun triggerCompletion() {
- val text = getCurrentEditingText()
- if (text.isEmpty()) {
- return
- }
-
- val result = CompletionManager.tryCompleteFor(text)
- if (!result.hasResult()) {
- // A provider accepted the task
- // But no candidates are provided
- // Give it zero angrily!
- result.markScore(0)
- onFinishCompletion()
- return
- }
- showAutoCompleteCandidates(result)
- }
-
- private fun showAutoCompleteCandidates(result: CompletionResult) {
- val termView = terminalView
- var popWindow = popupWindow
-
- if (termView == null) {
- return
- }
-
- if (popWindow == null) {
- popWindow = CandidatePopupWindow(termView.context)
- popWindow.onCandidateSelectedListener = this
- this.popupWindow = popWindow
- }
-
- popWindow.candidates = result.candidates
- popWindow.show(termView)
- }
-
- private fun getCurrentEditingText(): String {
- val builder = StringBuilder()
- val size = inputStack.size
- var start = inputStack.lastIndexOf(' ')
- if (start < 0) {
- // Yes, it is -1, we will do `start + 1` below.
- start = -1
- }
-
- IntRange(start + 1, size - 1)
- .map { inputStack[it] }
- .takeWhile { !(it == 0.toChar() || it == ' ') }
- .forEach { builder.append(it) }
- return builder.toString()
- }
-
- private fun clearChars() {
- inputStack.clear()
- lastCompletedIndex = 0
- }
-
- private fun popChar() {
- if (inputStack.isNotEmpty()) {
- inputStack.pop()
- }
- }
-
- private fun pushString(string: String) {
- string.toCharArray().forEach { pushChar(it) }
- }
-
- private fun pushChar(char: Char) {
- inputStack.push(char)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt
deleted file mode 100644
index 53f4ddf..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionCallback.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.neoterm.frontend.session.shell.client
-
-import android.content.ClipData
-import android.content.ClipboardManager
-import android.content.Context
-import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.session.shell.ShellTermSession
-
-/**
- * @author kiva
- */
-class TermSessionCallback : TerminalSession.SessionChangedCallback {
- var termSessionData: TermSessionData? = null
-
- var bellController: BellController? = null
-
- override fun onTextChanged(changedSession: TerminalSession?) {
- termSessionData?.termView?.onScreenUpdated()
- }
-
- override fun onTitleChanged(changedSession: TerminalSession?) {
- if (changedSession?.title != null) {
- termSessionData?.termUI?.requireUpdateTitle(changedSession.title)
- }
- }
-
- override fun onSessionFinished(finishedSession: TerminalSession?) {
- termSessionData?.termUI?.requireOnSessionFinished()
- }
-
- override fun onClipboardText(session: TerminalSession?, text: String?) {
- val termView = termSessionData?.termView
- if (termView != null) {
- val clipboard = termView.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
- clipboard.primaryClip = ClipData.newPlainText("", text)
- }
- }
-
- override fun onBell(session: TerminalSession?) {
- val termView = termSessionData?.termView ?: return
- val shellSession = session as ShellTermSession
-
- if (bellController == null) {
- bellController = BellController()
- }
-
- bellController?.bellOrVibrate(termView.context, shellSession)
- }
-
- override fun onColorsChanged(session: TerminalSession?) {
- val termView = termSessionData?.termView
- if (session != null && termView != null) {
- termView.onScreenUpdated()
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermUiPresenter.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/TermUiPresenter.kt
deleted file mode 100644
index b1c1ea3..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermUiPresenter.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.neoterm.frontend.session.shell.client
-
-/**
- * @author kiva
- */
-interface TermUiPresenter {
- fun requireClose()
- fun requireToggleFullScreen()
- fun requirePaste()
- fun requireUpdateTitle(title: String?)
- fun requireOnSessionFinished()
- fun requireHideIme()
- fun requireFinishAutoCompletion(): Boolean
- fun requireCreateNew()
- fun requireSwitchToPrevious()
- fun requireSwitchToNext()
- fun requireSwitchTo(index: Int)
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/CreateNewSessionEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/CreateNewSessionEvent.kt
deleted file mode 100644
index c42f28a..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/CreateNewSessionEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class CreateNewSessionEvent
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchIndexedSessionEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchIndexedSessionEvent.kt
deleted file mode 100644
index 9287238..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchIndexedSessionEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class SwitchIndexedSessionEvent(val index: Int)
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchSessionEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchSessionEvent.kt
deleted file mode 100644
index 1fce05e..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/SwitchSessionEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class SwitchSessionEvent(val toNext: Boolean)
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TabCloseEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TabCloseEvent.kt
deleted file mode 100644
index 2a0104b..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TabCloseEvent.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-import io.neoterm.ui.term.tab.TermTab
-
-/**
- * @author kiva
- */
-
-class TabCloseEvent(var termTab: TermTab)
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TitleChangedEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TitleChangedEvent.kt
deleted file mode 100644
index 5a7404e..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/TitleChangedEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class TitleChangedEvent(val title: String)
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleFullScreenEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleFullScreenEvent.kt
deleted file mode 100644
index d25c014..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleFullScreenEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class ToggleFullScreenEvent()
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleImeEvent.kt b/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleImeEvent.kt
deleted file mode 100644
index 363e9af..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/event/ToggleImeEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package io.neoterm.frontend.session.shell.client.event
-
-/**
- * @author kiva
- */
-class ToggleImeEvent
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt b/app/src/main/java/io/neoterm/frontend/session/terminal/data.kt
similarity index 65%
rename from app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt
rename to app/src/main/java/io/neoterm/frontend/session/terminal/data.kt
index 6e940e7..8ace818 100644
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermSessionData.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/terminal/data.kt
@@ -1,15 +1,12 @@
-package io.neoterm.frontend.session.shell.client
+package io.neoterm.frontend.session.terminal
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
-import io.neoterm.frontend.session.shell.ShellProfile
-import io.neoterm.frontend.session.shell.ShellTermSession
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.completion.OnAutoCompleteListener
+import io.neoterm.component.session.ShellProfile
+import io.neoterm.component.session.ShellTermSession
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
-/**
- * @author kiva
- */
class TermSessionData {
var termSession: TerminalSession? = null
var sessionCallback: TermSessionCallback? = null
@@ -58,4 +55,18 @@ class TermSessionData {
this.termView = termView
this.extraKeysView = eks
}
-}
\ No newline at end of file
+}
+
+interface TermUiPresenter {
+ fun requireClose()
+ fun requireToggleFullScreen()
+ fun requirePaste()
+ fun requireUpdateTitle(title: String?)
+ fun requireOnSessionFinished()
+ fun requireHideIme()
+ fun requireFinishAutoCompletion(): Boolean
+ fun requireCreateNew()
+ fun requireSwitchToPrevious()
+ fun requireSwitchToNext()
+ fun requireSwitchTo(index: Int)
+}
diff --git a/app/src/main/java/io/neoterm/frontend/session/terminal/events.kt b/app/src/main/java/io/neoterm/frontend/session/terminal/events.kt
new file mode 100644
index 0000000..444e376
--- /dev/null
+++ b/app/src/main/java/io/neoterm/frontend/session/terminal/events.kt
@@ -0,0 +1,11 @@
+package io.neoterm.frontend.session.terminal
+
+import io.neoterm.ui.term.TermTab
+
+class CreateNewSessionEvent
+class SwitchIndexedSessionEvent(val index: Int)
+class SwitchSessionEvent(val toNext: Boolean)
+class TabCloseEvent(val termTab: TermTab)
+class TitleChangedEvent(val title: String)
+class ToggleFullScreenEvent
+class ToggleImeEvent
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/BasicViewClient.kt b/app/src/main/java/io/neoterm/frontend/session/terminal/term-basic.kt
similarity index 64%
rename from app/src/main/java/io/neoterm/frontend/session/shell/client/BasicViewClient.kt
rename to app/src/main/java/io/neoterm/frontend/session/terminal/term-basic.kt
index b1bd0d6..7b6f513 100644
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/BasicViewClient.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/terminal/term-basic.kt
@@ -1,17 +1,40 @@
-package io.neoterm.frontend.session.shell.client
+package io.neoterm.frontend.session.terminal
import android.content.Context
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.inputmethod.InputMethodManager
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.TerminalViewClient
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.TerminalViewClient
+
+open class BasicSessionCallback(var terminalView: TerminalView) : TerminalSession.SessionChangedCallback {
+ override fun onTextChanged(changedSession: TerminalSession?) {
+ if (changedSession != null) {
+ terminalView.onScreenUpdated()
+ }
+ }
+
+ override fun onTitleChanged(changedSession: TerminalSession?) {
+ }
+
+ override fun onSessionFinished(finishedSession: TerminalSession?) {
+ }
+
+ override fun onClipboardText(session: TerminalSession?, text: String?) {
+ }
+
+ override fun onBell(session: TerminalSession?) {
+ }
+
+ override fun onColorsChanged(session: TerminalSession?) {
+ if (session != null) {
+ terminalView.onScreenUpdated()
+ }
+ }
+}
-/**
- * @author kiva
- */
class BasicViewClient(val terminalView: TerminalView) : TerminalViewClient {
override fun onScale(scale: Float): Float {
if (scale < 0.9f || scale > 1.1f) {
diff --git a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt b/app/src/main/java/io/neoterm/frontend/session/terminal/term-standard.kt
similarity index 55%
rename from app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt
rename to app/src/main/java/io/neoterm/frontend/session/terminal/term-standard.kt
index 5392031..9fa7859 100644
--- a/app/src/main/java/io/neoterm/frontend/session/shell/client/TermViewClient.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/terminal/term-standard.kt
@@ -1,20 +1,30 @@
-package io.neoterm.frontend.session.shell.client
+package io.neoterm.frontend.session.terminal
+import android.content.ClipData
+import android.content.ClipboardManager
import android.content.Context
import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Vibrator
+import android.util.Log
import android.view.InputDevice
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
+import io.neoterm.BuildConfig
+import io.neoterm.R
import io.neoterm.backend.KeyHandler
import io.neoterm.backend.TerminalSession
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.completion.*
+import io.neoterm.component.config.NeoPreference
import io.neoterm.component.extrakey.ExtraKeyComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.session.shell.ShellTermSession
-import io.neoterm.frontend.terminal.TerminalViewClient
-
+import io.neoterm.component.session.ShellTermSession
+import io.neoterm.frontend.completion.CandidatePopupWindow
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.TerminalViewClient
+import java.util.*
/**
* @author kiva
@@ -267,4 +277,234 @@ class TermViewClient(val context: Context) : TerminalViewClient {
NeoPreference.store(NeoPreference.KEY_FONT_SIZE, fontSize)
}
}
-}
\ No newline at end of file
+}
+
+/**
+ * @author kiva
+ */
+class TermSessionCallback : TerminalSession.SessionChangedCallback {
+ var termSessionData: TermSessionData? = null
+
+ var bellController: BellController? = null
+
+ override fun onTextChanged(changedSession: TerminalSession?) {
+ termSessionData?.termView?.onScreenUpdated()
+ }
+
+ override fun onTitleChanged(changedSession: TerminalSession?) {
+ if (changedSession?.title != null) {
+ termSessionData?.termUI?.requireUpdateTitle(changedSession.title)
+ }
+ }
+
+ override fun onSessionFinished(finishedSession: TerminalSession?) {
+ termSessionData?.termUI?.requireOnSessionFinished()
+ }
+
+ override fun onClipboardText(session: TerminalSession?, text: String?) {
+ val termView = termSessionData?.termView
+ if (termView != null) {
+ val clipboard = termView.context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
+ clipboard.primaryClip = ClipData.newPlainText("", text)
+ }
+ }
+
+ override fun onBell(session: TerminalSession?) {
+ val termView = termSessionData?.termView ?: return
+ val shellSession = session as ShellTermSession
+
+ if (bellController == null) {
+ bellController = BellController()
+ }
+
+ bellController?.bellOrVibrate(termView.context, shellSession)
+ }
+
+ override fun onColorsChanged(session: TerminalSession?) {
+ val termView = termSessionData?.termView
+ if (session != null && termView != null) {
+ termView.onScreenUpdated()
+ }
+ }
+}
+
+class BellController {
+ companion object {
+ private val BELL_DELAY_MS = 100
+ }
+
+ private var bellId: Int = 0
+ private var soundPool: SoundPool? = null
+ private var lastBellTime = 0L
+
+ fun bellOrVibrate(context: Context, session: ShellTermSession) {
+ val currentTime = System.currentTimeMillis()
+ if (currentTime - lastBellTime < BELL_DELAY_MS) {
+ return
+ }
+ lastBellTime = currentTime
+
+ if (session.shellProfile.enableBell) {
+ if (soundPool == null) {
+ soundPool = SoundPool.Builder().setMaxStreams(1).build()
+ bellId = soundPool!!.load(context, R.raw.bell, 1)
+ }
+ soundPool?.play(bellId, 1f, 1f, 0, 0, 1f)
+ }
+
+ if (session.shellProfile.enableVibrate) {
+ val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+ vibrator.vibrate(100)
+ }
+ }
+}
+
+class TermCompleteListener(var terminalView: TerminalView?) : OnAutoCompleteListener, OnCandidateSelectedListener {
+ private val inputStack = Stack()
+ private var popupWindow: CandidatePopupWindow? = null
+ private var lastCompletedIndex = 0
+
+ override fun onKeyCode(keyCode: Int, keyMod: Int) {
+ when (keyCode) {
+ KeyEvent.KEYCODE_DEL -> {
+ popChar()
+ fixLastCompletedIndex()
+ triggerCompletion()
+ }
+
+ KeyEvent.KEYCODE_ENTER -> {
+ clearChars()
+ popupWindow?.dismiss()
+ }
+ }
+ }
+
+ private fun fixLastCompletedIndex() {
+ val currentText = getCurrentEditingText()
+ lastCompletedIndex = minOf(lastCompletedIndex, currentText.length - 1)
+ }
+
+ override fun onCompletionRequired(newText: String?) {
+ if (newText == null || newText.isEmpty()) {
+ return
+ }
+ pushString(newText)
+ triggerCompletion()
+ }
+
+ override fun onCleanUp() {
+ popupWindow?.dismiss()
+ popupWindow?.cleanup()
+ popupWindow = null
+ terminalView = null
+ }
+
+ override fun onFinishCompletion(): Boolean {
+ val popWindow = popupWindow ?: return false
+
+ if (popWindow.isShowing()) {
+ popWindow.dismiss()
+ return true
+ }
+ return false
+ }
+
+ override fun onCandidateSelected(candidate: CompletionCandidate) {
+ val session = terminalView?.currentSession ?: return
+ val textNeedCompletion = getCurrentEditingText().substring(lastCompletedIndex + 1)
+ val newText = candidate.completeString
+
+ val deleteLength = newText.indexOf(textNeedCompletion) + textNeedCompletion.length
+ if (deleteLength > 0) {
+ for (i in 0 until deleteLength) {
+ session.write("\b")
+ popChar()
+ }
+ }
+
+ if (BuildConfig.DEBUG) {
+ Log.e(
+ "NeoTerm-AC",
+ "currentEditing: $textNeedCompletion, " +
+ "deleteLength: $deleteLength, completeString: $newText"
+ )
+ }
+
+ pushString(newText)
+ session.write(newText)
+ // Trigger next completion
+ lastCompletedIndex = inputStack.size
+ triggerCompletion()
+ }
+
+ private fun triggerCompletion() {
+ val text = getCurrentEditingText()
+ if (text.isEmpty()) {
+ return
+ }
+
+ val result = CompletionManager.tryCompleteFor(text)
+ if (!result.hasResult()) {
+ // A provider accepted the task
+ // But no candidates are provided
+ // Give it zero angrily!
+ result.markScore(0)
+ onFinishCompletion()
+ return
+ }
+ showAutoCompleteCandidates(result)
+ }
+
+ private fun showAutoCompleteCandidates(result: CompletionResult) {
+ val termView = terminalView
+ var popWindow = popupWindow
+
+ if (termView == null) {
+ return
+ }
+
+ if (popWindow == null) {
+ popWindow = CandidatePopupWindow(termView.context)
+ popWindow.onCandidateSelectedListener = this
+ this.popupWindow = popWindow
+ }
+
+ popWindow.candidates = result.candidates
+ popWindow.show(termView)
+ }
+
+ private fun getCurrentEditingText(): String {
+ val builder = StringBuilder()
+ val size = inputStack.size
+ var start = inputStack.lastIndexOf(' ')
+ if (start < 0) {
+ // Yes, it is -1, we will do `start + 1` below.
+ start = -1
+ }
+
+ IntRange(start + 1, size - 1)
+ .map { inputStack[it] }
+ .takeWhile { !(it == 0.toChar() || it == ' ') }
+ .forEach { builder.append(it) }
+ return builder.toString()
+ }
+
+ private fun clearChars() {
+ inputStack.clear()
+ lastCompletedIndex = 0
+ }
+
+ private fun popChar() {
+ if (inputStack.isNotEmpty()) {
+ inputStack.pop()
+ }
+ }
+
+ private fun pushString(string: String) {
+ string.toCharArray().forEach { pushChar(it) }
+ }
+
+ private fun pushChar(char: Char) {
+ inputStack.push(char)
+ }
+}
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/GestureAndScaleRecognizer.kt b/app/src/main/java/io/neoterm/frontend/session/view/GestureAndScaleRecognizer.kt
old mode 100755
new mode 100644
similarity index 99%
rename from app/src/main/java/io/neoterm/frontend/terminal/GestureAndScaleRecognizer.kt
rename to app/src/main/java/io/neoterm/frontend/session/view/GestureAndScaleRecognizer.kt
index 6ed3b32..0e8167d
--- a/app/src/main/java/io/neoterm/frontend/terminal/GestureAndScaleRecognizer.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/view/GestureAndScaleRecognizer.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal
+package io.neoterm.frontend.session.view
import android.content.Context
import android.view.GestureDetector
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/TerminalRenderer.java b/app/src/main/java/io/neoterm/frontend/session/view/TerminalRenderer.java
old mode 100755
new mode 100644
similarity index 99%
rename from app/src/main/java/io/neoterm/frontend/terminal/TerminalRenderer.java
rename to app/src/main/java/io/neoterm/frontend/session/view/TerminalRenderer.java
index a8ee1f5..bb9296d
--- a/app/src/main/java/io/neoterm/frontend/terminal/TerminalRenderer.java
+++ b/app/src/main/java/io/neoterm/frontend/session/view/TerminalRenderer.java
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal;
+package io.neoterm.frontend.session.view;
import android.graphics.Canvas;
import android.graphics.Paint;
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java b/app/src/main/java/io/neoterm/frontend/session/view/TerminalView.java
old mode 100755
new mode 100644
similarity index 96%
rename from app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java
rename to app/src/main/java/io/neoterm/frontend/session/view/TerminalView.java
index 9127825..3b28ce9
--- a/app/src/main/java/io/neoterm/frontend/terminal/TerminalView.java
+++ b/app/src/main/java/io/neoterm/frontend/session/view/TerminalView.java
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal;
+package io.neoterm.frontend.session.view;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
@@ -23,7 +23,7 @@ import android.view.inputmethod.InputConnection;
import android.widget.Scroller;
import io.neoterm.R;
import io.neoterm.backend.*;
-import io.neoterm.frontend.completion.listener.OnAutoCompleteListener;
+import io.neoterm.component.completion.OnAutoCompleteListener;
/**
* View displaying and interacting with a {@link TerminalSession}.
@@ -1032,45 +1032,38 @@ public final class TerminalView extends View {
@Override
public void onDestroyActionMode(ActionMode mode) {
}
-
};
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- mActionMode = startActionMode(new ActionMode.Callback2() {
- @Override
- public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- return callback.onCreateActionMode(mode, menu);
- }
+ mActionMode = startActionMode(new ActionMode.Callback2() {
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ return callback.onCreateActionMode(mode, menu);
+ }
- @Override
- public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
- return false;
- }
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
- @Override
- public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
- return callback.onActionItemClicked(mode, item);
- }
-
- @Override
- public void onDestroyActionMode(ActionMode mode) {
- // Ignore.
- }
-
- @Override
- public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
- int x1 = Math.round(mSelX1 * mRenderer.mFontWidth);
- int x2 = Math.round(mSelX2 * mRenderer.mFontWidth);
- int y1 = Math.round((mSelY1 - mTopRow) * mRenderer.mFontLineSpacing);
- int y2 = Math.round((mSelY2 + 1 - mTopRow) * mRenderer.mFontLineSpacing);
- outRect.set(Math.min(x1, x2), y1, Math.max(x1, x2), y2);
- }
- }, ActionMode.TYPE_FLOATING);
- } else {
- mActionMode = startActionMode(callback);
- }
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ return callback.onActionItemClicked(mode, item);
+ }
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ // Ignore.
+ }
+ @Override
+ public void onGetContentRect(ActionMode mode, View view, Rect outRect) {
+ int x1 = Math.round(mSelX1 * mRenderer.mFontWidth);
+ int x2 = Math.round(mSelX2 * mRenderer.mFontWidth);
+ int y1 = Math.round((mSelY1 - mTopRow) * mRenderer.mFontLineSpacing);
+ int y2 = Math.round((mSelY2 + 1 - mTopRow) * mRenderer.mFontLineSpacing);
+ outRect.set(Math.min(x1, x2), y1, Math.max(x1, x2), y2);
+ }
+ }, ActionMode.TYPE_FLOATING);
invalidate();
} else {
mActionMode.finish();
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/TerminalViewClient.java b/app/src/main/java/io/neoterm/frontend/session/view/TerminalViewClient.java
old mode 100755
new mode 100644
similarity index 96%
rename from app/src/main/java/io/neoterm/frontend/terminal/TerminalViewClient.java
rename to app/src/main/java/io/neoterm/frontend/session/view/TerminalViewClient.java
index b5a6eb1..451cbdc
--- a/app/src/main/java/io/neoterm/frontend/terminal/TerminalViewClient.java
+++ b/app/src/main/java/io/neoterm/frontend/session/view/TerminalViewClient.java
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal;
+package io.neoterm.frontend.session.view;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -11,7 +11,6 @@ import io.neoterm.backend.TerminalSession;
*
*/
public interface TerminalViewClient {
-
/**
* Callback function on scale events according to {@link ScaleGestureDetector#getScaleFactor()}.
*/
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/combine/CombinedSequence.kt b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/CombinedSequence.kt
similarity index 91%
rename from app/src/main/java/io/neoterm/frontend/terminal/extrakey/combine/CombinedSequence.kt
rename to app/src/main/java/io/neoterm/frontend/session/view/extrakey/CombinedSequence.kt
index d3227fc..4e6b91d 100644
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/combine/CombinedSequence.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/CombinedSequence.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal.extrakey.combine
+package io.neoterm.frontend.session.view.extrakey
/**
*
@@ -26,4 +26,4 @@ class CombinedSequence private constructor() {
return seq
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/ExtraKeysView.kt b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/ExtraKeysView.kt
old mode 100755
new mode 100644
similarity index 91%
rename from app/src/main/java/io/neoterm/frontend/terminal/extrakey/ExtraKeysView.kt
rename to app/src/main/java/io/neoterm/frontend/session/view/extrakey/ExtraKeysView.kt
index ee22fe0..3dd83e9
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/ExtraKeysView.kt
+++ b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/ExtraKeysView.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.terminal.extrakey
+package io.neoterm.frontend.session.view.extrakey
import android.content.Context
import android.graphics.Typeface
@@ -7,21 +7,15 @@ import android.view.*
import android.widget.GridLayout
import android.widget.LinearLayout
import io.neoterm.R
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.config.NeoTermPath
import io.neoterm.component.extrakey.ExtraKeyComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.session.shell.client.event.ToggleImeEvent
-import io.neoterm.frontend.terminal.extrakey.button.ControlButton
-import io.neoterm.frontend.terminal.extrakey.button.IExtraButton
-import io.neoterm.frontend.terminal.extrakey.button.RepeatableButton
-import io.neoterm.frontend.terminal.extrakey.button.StatedControlButton
-import io.neoterm.frontend.terminal.extrakey.impl.ArrowButton
+import io.neoterm.frontend.session.terminal.ToggleImeEvent
import org.greenrobot.eventbus.EventBus
import java.io.File
class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
-
companion object {
private val ESC = ControlButton(IExtraButton.KEY_ESC)
private val TAB = ControlButton(IExtraButton.KEY_TAB)
@@ -68,7 +62,7 @@ class ExtraKeysView(context: Context, attrs: AttributeSet) : LinearLayout(contex
init {
alpha = DEFAULT_ALPHA
gravity = Gravity.TOP
- orientation = LinearLayout.VERTICAL
+ orientation = VERTICAL
typeface = Typeface.createFromAsset(context.assets, "eks_font.ttf")
extraKeyComponent = ComponentManager.getComponent()
diff --git a/app/src/main/java/io/neoterm/frontend/session/view/extrakey/buttons.kt b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/buttons.kt
new file mode 100644
index 0000000..9955457
--- /dev/null
+++ b/app/src/main/java/io/neoterm/frontend/session/view/extrakey/buttons.kt
@@ -0,0 +1,222 @@
+package io.neoterm.frontend.session.view.extrakey
+
+import android.content.Context
+import android.os.Handler
+import android.os.Looper
+import android.util.AttributeSet
+import android.view.KeyEvent
+import android.view.MotionEvent
+import android.view.View
+import android.widget.Button
+import android.widget.ToggleButton
+import androidx.appcompat.widget.AppCompatButton
+import io.neoterm.R
+import io.neoterm.frontend.session.view.TerminalView
+
+/**
+ * @author kiva
+ */
+
+open class ControlButton(text: String) : TextButton(text, false)
+
+/**
+ * @author kiva
+ */
+
+abstract class IExtraButton : View.OnClickListener {
+
+ var buttonKeys: CombinedSequence? = null
+ var displayText: String? = null
+
+ override fun toString(): String {
+ return "${this.javaClass.simpleName} { display: $displayText, code: ${buttonKeys?.keys} }"
+ }
+
+ abstract override fun onClick(view: View)
+
+ abstract fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button
+
+ companion object {
+ const val KEY_ESC = "Esc"
+ const val KEY_TAB = "Tab"
+ const val KEY_CTRL = "Ctrl"
+ const val KEY_ALT = "Alt"
+ const val KEY_PAGE_UP = "PgUp"
+ const val KEY_PAGE_DOWN = "PgDn"
+ const val KEY_HOME = "Home"
+ const val KEY_END = "End"
+ const val KEY_ARROW_UP_TEXT = "Up"
+ const val KEY_ARROW_DOWN_TEXT = "Down"
+ const val KEY_ARROW_LEFT_TEXT = "Left"
+ const val KEY_ARROW_RIGHT_TEXT = "Right"
+ const val KEY_SHOW_ALL_BUTTONS = "···"
+ const val KEY_TOGGLE_IME = "Im"
+
+ const val KEY_ARROW_UP = "▲"
+ const val KEY_ARROW_DOWN = "▼"
+ const val KEY_ARROW_LEFT = "◀"
+ const val KEY_ARROW_RIGHT = "▶"
+
+ var NORMAL_TEXT_COLOR = 0xFFFFFFFF.toInt()
+ var SELECTED_TEXT_COLOR = 0xFF80DEEA.toInt()
+
+ fun sendKey(view: View, keyName: String) {
+ var keyCode = 0
+ var chars = ""
+ when (keyName) {
+ KEY_ESC -> keyCode = KeyEvent.KEYCODE_ESCAPE
+ KEY_TAB -> keyCode = KeyEvent.KEYCODE_TAB
+ KEY_ARROW_UP -> keyCode = KeyEvent.KEYCODE_DPAD_UP
+ KEY_ARROW_LEFT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
+ KEY_ARROW_RIGHT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
+ KEY_ARROW_DOWN -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
+ KEY_ARROW_UP_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_UP
+ KEY_ARROW_LEFT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
+ KEY_ARROW_RIGHT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
+ KEY_ARROW_DOWN_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
+ KEY_PAGE_UP -> keyCode = KeyEvent.KEYCODE_PAGE_UP
+ KEY_PAGE_DOWN -> keyCode = KeyEvent.KEYCODE_PAGE_DOWN
+ KEY_HOME -> keyCode = KeyEvent.KEYCODE_MOVE_HOME
+ KEY_END -> keyCode = KeyEvent.KEYCODE_MOVE_END
+ "―" -> chars = "-"
+ else -> chars = keyName
+ }
+
+ if (keyCode > 0) {
+ view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, keyCode))
+ view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, keyCode))
+ } else if (chars.isNotEmpty()) {
+ val terminalView = view.findViewById(R.id.terminal_view)
+ val session = terminalView.currentSession
+ session?.write(chars)
+ }
+ }
+ }
+}
+
+/**
+ * @author kiva
+ */
+open class RepeatableButton(buttonText: String) : ControlButton(buttonText) {
+
+ override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
+ return RepeatableButtonWidget(context, attrs, defStyleAttr)
+ }
+
+ private class RepeatableButtonWidget(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
+ AppCompatButton(context!!, attrs, defStyleAttr) {
+
+ /**
+ * Milliseconds how long we trigger an action
+ * when long pressing
+ */
+ private val LONG_CLICK_ACTION_INTERVAL = 100L
+
+ private var isMotionEventUp = true
+
+ var mHandler: Handler = object : Handler(Looper.getMainLooper()) {
+ override fun handleMessage(msg: android.os.Message) {
+ if (!isMotionEventUp && isEnabled) {
+ performClick()
+ this.sendEmptyMessageDelayed(0, LONG_CLICK_ACTION_INTERVAL)
+ }
+ }
+ }
+
+ init {
+ this.setOnLongClickListener {
+ isMotionEventUp = false
+ mHandler.sendEmptyMessage(0)
+ false
+ }
+ this.setOnTouchListener { _, event ->
+ if (event.action == MotionEvent.ACTION_UP) {
+ isMotionEventUp = true
+ }
+ false
+ }
+ }
+
+ override fun performClick(): Boolean {
+ return super.performClick()
+ }
+ }
+}
+
+/**
+ * @author kiva
+ */
+
+open class StatedControlButton @JvmOverloads constructor(text: String, var initState: Boolean = false) :
+ ControlButton(text) {
+ var toggleButton: ToggleButton? = null
+
+ override fun onClick(view: View) {
+ setStatus(toggleButton?.isChecked)
+ }
+
+ override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
+ val outerButton = ToggleButton(context, null, android.R.attr.buttonBarButtonStyle)
+
+ outerButton.isClickable = true
+ if (initState) {
+ outerButton.isChecked = true
+ outerButton.setTextColor(SELECTED_TEXT_COLOR)
+ }
+
+ this.toggleButton = outerButton
+ return outerButton
+ }
+
+ private fun setStatus(status: Boolean?) {
+ val button = toggleButton
+ if (button != null && status != null) {
+ button.isChecked = status
+ button.setTextColor(
+ if (status) SELECTED_TEXT_COLOR
+ else NORMAL_TEXT_COLOR
+ )
+ }
+ }
+
+ fun readState(): Boolean {
+ val button = toggleButton ?: return false
+
+ if (button.isPressed) return true
+ val result = button.isChecked
+ if (result) {
+ button.isChecked = false
+ button.setTextColor(NORMAL_TEXT_COLOR)
+ }
+ return result
+ }
+}
+
+/**
+ * @author kiva
+ */
+
+open class TextButton constructor(text: String, val withEnter: Boolean = false) : IExtraButton() {
+ init {
+ this.buttonKeys = CombinedSequence.solveString(text)
+ this.displayText = text
+ }
+
+ override fun onClick(view: View) {
+ buttonKeys!!.keys.forEach {
+ sendKey(view, it)
+ }
+ if (withEnter) {
+ sendKey(view, "\n")
+ }
+ }
+
+ override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
+ return Button(context, attrs, defStyleAttr)
+ }
+}
+
+/**
+ * @author kiva
+ */
+class ArrowButton(arrowText: String) : RepeatableButton(arrowText)
diff --git a/app/src/main/java/io/neoterm/frontend/session/xorg/XParameter.java b/app/src/main/java/io/neoterm/frontend/session/xorg/XParameter.java
deleted file mode 100644
index 5f67a17..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/xorg/XParameter.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.neoterm.frontend.session.xorg;
-
-/**
- * @author kiva
- */
-
-public class XParameter {
-}
diff --git a/app/src/main/java/io/neoterm/frontend/session/xorg/client/XSessionData.kt b/app/src/main/java/io/neoterm/frontend/session/xorg/client/XSessionData.kt
deleted file mode 100644
index aa9cac2..0000000
--- a/app/src/main/java/io/neoterm/frontend/session/xorg/client/XSessionData.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package io.neoterm.frontend.session.xorg.client
-
-import android.view.View
-import android.widget.FrameLayout
-import io.neoterm.NeoAudioThread
-import io.neoterm.NeoGLView
-import io.neoterm.xorg.NeoXorgViewClient
-import java.util.*
-
-/**
- * @author kiva
- */
-class XSessionData {
- var videoLayout: FrameLayout? = null
- var audioThread: NeoAudioThread? = null
- var screenKeyboard: View? = null
- var glView: NeoGLView? = null
-
- var isPaused = false
- var client: NeoXorgViewClient? = null
-
- var keyboardWithoutTextInputShown = false
- var screenKeyboardHintMessage: String? = null
- var textInput = LinkedList()
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/ControlButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/ControlButton.kt
deleted file mode 100644
index e9a1ff7..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/ControlButton.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.button
-
-/**
- * @author kiva
- */
-
-open class ControlButton(text: String) : TextButton(text, false)
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/IExtraButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/IExtraButton.kt
deleted file mode 100644
index 1a0b1dd..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/IExtraButton.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.button
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.KeyEvent
-import android.view.View
-import android.widget.Button
-import io.neoterm.R
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.combine.CombinedSequence
-
-/**
- * @author kiva
- */
-
-abstract class IExtraButton : View.OnClickListener {
-
- var buttonKeys: CombinedSequence? = null
- var displayText: String? = null
-
- override fun toString(): String {
- return "${this.javaClass.simpleName} { display: $displayText, code: ${buttonKeys?.keys} }"
- }
-
- abstract override fun onClick(view: View)
-
- abstract fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button
-
- companion object {
- val KEY_ESC = "Esc"
- val KEY_TAB = "Tab"
- val KEY_CTRL = "Ctrl"
- val KEY_ALT = "Alt"
- val KEY_PAGE_UP = "PgUp"
- val KEY_PAGE_DOWN = "PgDn"
- val KEY_HOME = "Home"
- val KEY_END = "End"
- val KEY_ARROW_UP_TEXT = "Up"
- val KEY_ARROW_DOWN_TEXT = "Down"
- val KEY_ARROW_LEFT_TEXT = "Left"
- val KEY_ARROW_RIGHT_TEXT = "Right"
- val KEY_SHOW_ALL_BUTTONS = "···"
- val KEY_TOGGLE_IME = "Im"
-
- val KEY_ARROW_UP = "▲"
- val KEY_ARROW_DOWN = "▼"
- val KEY_ARROW_LEFT = "◀"
- val KEY_ARROW_RIGHT = "▶"
-
- var NORMAL_TEXT_COLOR = 0xFFFFFFFF.toInt()
- var SELECTED_TEXT_COLOR = 0xFF80DEEA.toInt()
-
- fun sendKey(view: View, keyName: String) {
- var keyCode = 0
- var chars = ""
- when (keyName) {
- KEY_ESC -> keyCode = KeyEvent.KEYCODE_ESCAPE
- KEY_TAB -> keyCode = KeyEvent.KEYCODE_TAB
- KEY_ARROW_UP -> keyCode = KeyEvent.KEYCODE_DPAD_UP
- KEY_ARROW_LEFT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
- KEY_ARROW_RIGHT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
- KEY_ARROW_DOWN -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
- KEY_ARROW_UP_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_UP
- KEY_ARROW_LEFT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_LEFT
- KEY_ARROW_RIGHT_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_RIGHT
- KEY_ARROW_DOWN_TEXT -> keyCode = KeyEvent.KEYCODE_DPAD_DOWN
- KEY_PAGE_UP -> keyCode = KeyEvent.KEYCODE_PAGE_UP
- KEY_PAGE_DOWN -> keyCode = KeyEvent.KEYCODE_PAGE_DOWN
- KEY_HOME -> keyCode = KeyEvent.KEYCODE_MOVE_HOME
- KEY_END -> keyCode = KeyEvent.KEYCODE_MOVE_END
- "―" -> chars = "-"
- else -> chars = keyName
- }
-
- if (keyCode > 0) {
- view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, keyCode))
- view.dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_UP, keyCode))
- } else if (chars.isNotEmpty()) {
- val terminalView = view.findViewById(R.id.terminal_view)
- val session = terminalView.currentSession
- session?.write(chars)
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/RepeatableButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/RepeatableButton.kt
deleted file mode 100644
index 302a58e..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/RepeatableButton.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.button
-
-import android.content.Context
-import android.os.Handler
-import android.os.Looper
-import android.util.AttributeSet
-import android.view.MotionEvent
-import android.widget.Button
-import androidx.appcompat.widget.AppCompatButton
-
-
-/**
- * @author kiva
- */
-open class RepeatableButton(buttonText: String) : ControlButton(buttonText) {
-
- override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
- return RepeatableButtonWidget(context, attrs, defStyleAttr)
- }
-
- private class RepeatableButtonWidget(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) :
- AppCompatButton(context!!, attrs, defStyleAttr) {
-
- /**
- * Milliseconds how long we trigger an action
- * when long pressing
- */
- private val LONG_CLICK_ACTION_INTERVAL = 100L
-
- private var isMotionEventUp = true
-
- var mHandler: Handler = object : Handler(Looper.getMainLooper()) {
- override fun handleMessage(msg: android.os.Message) {
- if (!isMotionEventUp && isEnabled) {
- performClick()
- this.sendEmptyMessageDelayed(0, LONG_CLICK_ACTION_INTERVAL)
- }
- }
- }
-
- init {
- this.setOnLongClickListener {
- isMotionEventUp = false
- mHandler.sendEmptyMessage(0)
- false
- }
- this.setOnTouchListener { _, event ->
- if (event.action == MotionEvent.ACTION_UP) {
- isMotionEventUp = true
- }
- false
- }
- }
-
- override fun performClick(): Boolean {
- return super.performClick()
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/StatedControlButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/StatedControlButton.kt
deleted file mode 100644
index f5e1701..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/StatedControlButton.kt
+++ /dev/null
@@ -1,56 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.button
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.widget.Button
-import android.widget.ToggleButton
-
-/**
- * @author kiva
- */
-
-open class StatedControlButton @JvmOverloads constructor(text: String, var initState: Boolean = false) :
- ControlButton(text) {
- var toggleButton: ToggleButton? = null
-
- override fun onClick(view: View) {
- setStatus(toggleButton?.isChecked)
- }
-
- override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
- val outerButton = ToggleButton(context, null, android.R.attr.buttonBarButtonStyle)
-
- outerButton.isClickable = true
- if (initState) {
- outerButton.isChecked = true
- outerButton.setTextColor(IExtraButton.SELECTED_TEXT_COLOR)
- }
-
- this.toggleButton = outerButton
- return outerButton
- }
-
- private fun setStatus(status: Boolean?) {
- val button = toggleButton
- if (button != null && status != null) {
- button.isChecked = status
- button.setTextColor(
- if (status) SELECTED_TEXT_COLOR
- else NORMAL_TEXT_COLOR
- )
- }
- }
-
- fun readState(): Boolean {
- val button = toggleButton ?: return false
-
- if (button.isPressed) return true
- val result = button.isChecked
- if (result) {
- button.isChecked = false
- button.setTextColor(NORMAL_TEXT_COLOR)
- }
- return result
- }
-}
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/TextButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/TextButton.kt
deleted file mode 100644
index 9191a7e..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/button/TextButton.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.button
-
-import android.content.Context
-import android.util.AttributeSet
-import android.view.View
-import android.widget.Button
-import io.neoterm.frontend.terminal.extrakey.combine.CombinedSequence
-
-/**
- * @author kiva
- */
-
-open class TextButton constructor(text: String, val withEnter: Boolean = false) : IExtraButton() {
- init {
- this.buttonKeys = CombinedSequence.solveString(text)
- this.displayText = text
- }
-
- override fun onClick(view: View) {
- buttonKeys!!.keys.forEach {
- sendKey(view, it)
- }
- if (withEnter) {
- sendKey(view, "\n")
- }
- }
-
- override fun makeButton(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): Button {
- return Button(context, attrs, defStyleAttr)
- }
-}
diff --git a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/impl/ArrowButton.kt b/app/src/main/java/io/neoterm/frontend/terminal/extrakey/impl/ArrowButton.kt
deleted file mode 100644
index 1a6fc01..0000000
--- a/app/src/main/java/io/neoterm/frontend/terminal/extrakey/impl/ArrowButton.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.neoterm.frontend.terminal.extrakey.impl
-
-import io.neoterm.frontend.terminal.extrakey.button.RepeatableButton
-
-/**
- * @author kiva
- */
-class ArrowButton(arrowText: String) : RepeatableButton(arrowText)
diff --git a/app/src/main/java/io/neoterm/services/NeoTermService.kt b/app/src/main/java/io/neoterm/services/NeoTermService.kt
index c25b492..76ef9e6 100644
--- a/app/src/main/java/io/neoterm/services/NeoTermService.kt
+++ b/app/src/main/java/io/neoterm/services/NeoTermService.kt
@@ -14,11 +14,11 @@ import androidx.core.app.NotificationCompat
import io.neoterm.R
import io.neoterm.backend.EmulatorDebug
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.logging.NLog
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.xorg.XParameter
-import io.neoterm.frontend.session.xorg.XSession
+import io.neoterm.component.session.ShellParameter
+import io.neoterm.component.session.XParameter
+import io.neoterm.component.session.XSession
import io.neoterm.ui.term.NeoTermActivity
+import io.neoterm.utils.NLog
import io.neoterm.utils.Terminals
diff --git a/app/src/main/java/io/neoterm/setup/ResultListener.kt b/app/src/main/java/io/neoterm/setup/ResultListener.kt
deleted file mode 100644
index 3546064..0000000
--- a/app/src/main/java/io/neoterm/setup/ResultListener.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package io.neoterm.setup
-
-/**
- * @author kiva
- */
-interface ResultListener {
- fun onResult(error: Exception?)
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/setup/SetupThread.java b/app/src/main/java/io/neoterm/setup/SetupThread.java
index 00bf47b..42e5103 100644
--- a/app/src/main/java/io/neoterm/setup/SetupThread.java
+++ b/app/src/main/java/io/neoterm/setup/SetupThread.java
@@ -5,8 +5,8 @@ import android.system.Os;
import android.util.Pair;
import androidx.appcompat.app.AppCompatActivity;
import io.neoterm.backend.EmulatorDebug;
-import io.neoterm.frontend.config.NeoTermPath;
-import io.neoterm.frontend.logging.NLog;
+import io.neoterm.component.config.NeoTermPath;
+import io.neoterm.utils.NLog;
import java.io.*;
import java.util.ArrayList;
diff --git a/app/src/main/java/io/neoterm/setup/SourceConnection.java b/app/src/main/java/io/neoterm/setup/SourceConnection.java
index 4c73bea..0fe8f89 100644
--- a/app/src/main/java/io/neoterm/setup/SourceConnection.java
+++ b/app/src/main/java/io/neoterm/setup/SourceConnection.java
@@ -8,8 +8,6 @@ import java.io.InputStream;
*/
public interface SourceConnection {
InputStream getInputStream() throws IOException;
-
int getSize();
-
void close();
}
diff --git a/app/src/main/java/io/neoterm/setup/connections.kt b/app/src/main/java/io/neoterm/setup/connections.kt
new file mode 100644
index 0000000..8ba120a
--- /dev/null
+++ b/app/src/main/java/io/neoterm/setup/connections.kt
@@ -0,0 +1,113 @@
+package io.neoterm.setup
+
+import android.content.Context
+import android.net.Uri
+import java.io.IOException
+import java.io.InputStream
+import java.net.HttpURLConnection
+import java.net.URL
+
+/**
+ * @author kiva
+ */
+
+class BackupFileConnection(context: Context, uri: Uri) : LocalFileConnection(context, uri)
+
+/**
+ * @author kiva
+ */
+
+open class LocalFileConnection(context: Context, uri: Uri) : OfflineUriConnection(context, uri)
+
+/**
+ * @author kiva
+ */
+
+class NetworkConnection(private val sourceUrl: String) : SourceConnection {
+ private var connection: HttpURLConnection? = null
+
+ @Throws(IOException::class)
+ override fun getInputStream(): InputStream {
+ if (connection == null) {
+ connection = openHttpConnection()
+ connection!!.connectTimeout = 8000
+ connection!!.readTimeout = 8000
+ }
+ return connection!!.inputStream
+ }
+
+ override fun getSize(): Int {
+ return if (connection != null) {
+ connection!!.contentLength
+ } else 0
+
+ }
+
+ override fun close() {
+ if (connection != null) {
+ connection!!.disconnect()
+ }
+ }
+
+ @Throws(IOException::class)
+ private fun openHttpConnection(): HttpURLConnection {
+ val arch = SetupHelper.determineArchName()
+
+ return URL("$sourceUrl/boot/$arch.zip").openConnection() as HttpURLConnection
+ }
+}
+
+/**
+ * @author kiva
+ */
+
+abstract class OfflineConnection : SourceConnection {
+ private var inputStream: InputStream? = null
+
+ @Throws(IOException::class)
+ protected abstract fun openInputStream(): InputStream
+
+ @Throws(IOException::class)
+ override fun getInputStream(): InputStream {
+ if (inputStream == null) {
+ inputStream = openInputStream()
+ }
+ return inputStream!!
+ }
+
+ override fun getSize(): Int {
+ if (inputStream != null) {
+ return try {
+ inputStream!!.available()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ 0
+ }
+
+ }
+ return 0
+ }
+
+ override fun close() {
+ if (inputStream != null) {
+ try {
+ inputStream!!.close()
+ } catch (ignore: IOException) {
+ ignore.printStackTrace()
+ }
+
+ }
+ }
+}
+
+/**
+ * @author kiva
+ */
+
+open class OfflineUriConnection(private val context: Context, private val uri: Uri) : OfflineConnection() {
+
+ @Throws(IOException::class)
+ override fun openInputStream(): InputStream {
+ return context.contentResolver.openInputStream(uri)
+ }
+}
diff --git a/app/src/main/java/io/neoterm/setup/connections/BackupFileConnection.kt b/app/src/main/java/io/neoterm/setup/connections/BackupFileConnection.kt
deleted file mode 100644
index da71aeb..0000000
--- a/app/src/main/java/io/neoterm/setup/connections/BackupFileConnection.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.setup.connections
-
-import android.content.Context
-import android.net.Uri
-
-/**
- * @author kiva
- */
-
-class BackupFileConnection(context: Context, uri: Uri) : LocalFileConnection(context, uri)
diff --git a/app/src/main/java/io/neoterm/setup/connections/LocalFileConnection.kt b/app/src/main/java/io/neoterm/setup/connections/LocalFileConnection.kt
deleted file mode 100644
index 37f1dbb..0000000
--- a/app/src/main/java/io/neoterm/setup/connections/LocalFileConnection.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package io.neoterm.setup.connections
-
-import android.content.Context
-import android.net.Uri
-
-/**
- * @author kiva
- */
-
-open class LocalFileConnection(context: Context, uri: Uri) : OfflineUriConnection(context, uri)
diff --git a/app/src/main/java/io/neoterm/setup/connections/NetworkConnection.kt b/app/src/main/java/io/neoterm/setup/connections/NetworkConnection.kt
deleted file mode 100644
index 3b11fc8..0000000
--- a/app/src/main/java/io/neoterm/setup/connections/NetworkConnection.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package io.neoterm.setup.connections
-
-import io.neoterm.setup.SetupHelper
-import io.neoterm.setup.SourceConnection
-import java.io.IOException
-import java.io.InputStream
-import java.net.HttpURLConnection
-import java.net.URL
-
-/**
- * @author kiva
- */
-
-class NetworkConnection(private val sourceUrl: String) : SourceConnection {
- private var connection: HttpURLConnection? = null
-
- @Throws(IOException::class)
- override fun getInputStream(): InputStream {
- if (connection == null) {
- connection = openHttpConnection()
- connection!!.connectTimeout = 8000
- connection!!.readTimeout = 8000
- }
- return connection!!.inputStream
- }
-
- override fun getSize(): Int {
- return if (connection != null) {
- connection!!.contentLength
- } else 0
-
- }
-
- override fun close() {
- if (connection != null) {
- connection!!.disconnect()
- }
- }
-
- @Throws(IOException::class)
- private fun openHttpConnection(): HttpURLConnection {
- val arch = SetupHelper.determineArchName()
-
- return URL("$sourceUrl/boot/$arch.zip").openConnection() as HttpURLConnection
- }
-}
diff --git a/app/src/main/java/io/neoterm/setup/connections/OfflineConnection.kt b/app/src/main/java/io/neoterm/setup/connections/OfflineConnection.kt
deleted file mode 100644
index a1b8060..0000000
--- a/app/src/main/java/io/neoterm/setup/connections/OfflineConnection.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-package io.neoterm.setup.connections
-
-import io.neoterm.setup.SourceConnection
-import java.io.IOException
-import java.io.InputStream
-
-/**
- * @author kiva
- */
-
-abstract class OfflineConnection : SourceConnection {
- private var inputStream: InputStream? = null
-
- @Throws(IOException::class)
- protected abstract fun openInputStream(): InputStream
-
- @Throws(IOException::class)
- override fun getInputStream(): InputStream {
- if (inputStream == null) {
- inputStream = openInputStream()
- }
- return inputStream!!
- }
-
- override fun getSize(): Int {
- if (inputStream != null) {
- return try {
- inputStream!!.available()
- } catch (e: IOException) {
- e.printStackTrace()
- 0
- }
-
- }
- return 0
- }
-
- override fun close() {
- if (inputStream != null) {
- try {
- inputStream!!.close()
- } catch (ignore: IOException) {
- ignore.printStackTrace()
- }
-
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/setup/connections/OfflineUriConnection.kt b/app/src/main/java/io/neoterm/setup/connections/OfflineUriConnection.kt
deleted file mode 100644
index 5fa6193..0000000
--- a/app/src/main/java/io/neoterm/setup/connections/OfflineUriConnection.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package io.neoterm.setup.connections
-
-import android.content.Context
-import android.net.Uri
-
-import java.io.IOException
-import java.io.InputStream
-
-/**
- * @author kiva
- */
-
-open class OfflineUriConnection(private val context: Context, private val uri: Uri) : OfflineConnection() {
-
- @Throws(IOException::class)
- override fun openInputStream(): InputStream {
- return context.contentResolver.openInputStream(uri)
- }
-}
diff --git a/app/src/main/java/io/neoterm/setup/SetupHelper.kt b/app/src/main/java/io/neoterm/setup/setup.kt
similarity index 93%
rename from app/src/main/java/io/neoterm/setup/SetupHelper.kt
rename to app/src/main/java/io/neoterm/setup/setup.kt
index 81658a5..1bfca1a 100644
--- a/app/src/main/java/io/neoterm/setup/SetupHelper.kt
+++ b/app/src/main/java/io/neoterm/setup/setup.kt
@@ -7,10 +7,17 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import io.neoterm.App
import io.neoterm.R
-import io.neoterm.frontend.config.NeoTermPath
+import io.neoterm.component.config.NeoTermPath
import java.io.File
import java.util.*
+/**
+ * @author kiva
+ */
+interface ResultListener {
+ fun onResult(error: Exception?)
+}
+
/**
* @author kiva
*/
@@ -35,8 +42,7 @@ object SetupHelper {
progress.max = 100
progress.show()
- SetupThread(activity, connection, prefixFile, resultListener, progress)
- .start()
+ SetupThread(activity, connection, prefixFile, resultListener, progress).start()
}
private fun makeProgressDialog(context: Context): ProgressDialog {
diff --git a/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt b/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
index 0e21a34..ef60883 100644
--- a/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/customize/BaseCustomizeActivity.kt
@@ -6,12 +6,12 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import io.neoterm.R
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.shell.client.BasicSessionCallback
-import io.neoterm.frontend.session.shell.client.BasicViewClient
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.config.NeoTermPath
+import io.neoterm.component.session.ShellParameter
+import io.neoterm.frontend.session.terminal.BasicSessionCallback
+import io.neoterm.frontend.session.terminal.BasicViewClient
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
import io.neoterm.utils.Terminals
/**
@@ -56,4 +56,4 @@ open class BaseCustomizeActivity : AppCompatActivity() {
}
return super.onOptionsItemSelected(item)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/customize/ColorSchemeActivity.kt b/app/src/main/java/io/neoterm/ui/customize/ColorSchemeActivity.kt
index d824943..f21c989 100644
--- a/app/src/main/java/io/neoterm/ui/customize/ColorSchemeActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/customize/ColorSchemeActivity.kt
@@ -18,12 +18,10 @@ import es.dmoral.coloromatic.IndicatorMode
import es.dmoral.coloromatic.colormode.ColorMode
import io.neoterm.R
import io.neoterm.backend.TerminalColors
+import io.neoterm.component.ComponentManager
import io.neoterm.component.colorscheme.ColorSchemeComponent
import io.neoterm.component.colorscheme.NeoColorScheme
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.ui.customize.adapter.ColorItemAdapter
-import io.neoterm.ui.customize.model.ColorItem
+import io.neoterm.frontend.session.view.TerminalView
import io.neoterm.utils.Terminals
@@ -32,7 +30,7 @@ import io.neoterm.utils.Terminals
*/
class ColorSchemeActivity : BaseCustomizeActivity() {
private val COMPARATOR = SortedListAdapter.ComparatorBuilder()
- .setOrderForModel(ColorItem::class.java) { a, b ->
+ .setOrderForModel(ColorItem::class.java) { a, b ->
a.colorType.compareTo(b.colorType)
}
.build()
@@ -81,13 +79,13 @@ class ColorSchemeActivity : BaseCustomizeActivity() {
if (keyCode == KeyEvent.KEYCODE_BACK && event!!.action == KeyEvent.ACTION_DOWN && changed) {
AlertDialog.Builder(this)
.setMessage(getString(R.string.discard_changes))
- .setPositiveButton(R.string.save, { _, _ ->
+ .setPositiveButton(R.string.save) { _, _ ->
applyColorScheme(editingColorScheme, true)
- })
+ }
.setNegativeButton(android.R.string.no, null)
- .setNeutralButton(R.string.exit, { _, _ ->
+ .setNeutralButton(R.string.exit) { _, _ ->
finish()
- })
+ }
.show()
return true
}
@@ -135,10 +133,10 @@ class ColorSchemeActivity : BaseCustomizeActivity() {
.setTitle(model.colorName)
.setView(view)
.setNegativeButton(android.R.string.no, null)
- .setPositiveButton(android.R.string.yes, { _, _ ->
+ .setPositiveButton(android.R.string.yes) { _, _ ->
applyColor(edit.text.toString());
- })
- .setNeutralButton(R.string.select_new_value, { _, _ ->
+ }
+ .setNeutralButton(R.string.select_new_value) { _, _ ->
ColorOMaticDialog.Builder()
.initialColor(TerminalColors.parse(model.colorValue))
.colorMode(ColorMode.RGB)
@@ -149,7 +147,7 @@ class ColorSchemeActivity : BaseCustomizeActivity() {
.showColorIndicator(true)
.create()
.show(supportFragmentManager, "ColorOMaticDialog")
- })
+ }
.show()
}
@@ -164,10 +162,10 @@ class ColorSchemeActivity : BaseCustomizeActivity() {
AlertDialog.Builder(this)
.setTitle(R.string.save_color)
.setView(view)
- .setPositiveButton(android.R.string.yes, { _, _ ->
+ .setPositiveButton(android.R.string.yes) { _, _ ->
colorScheme.colorName = edit.text.toString()
applyColorScheme(colorScheme, finishAfter)
- })
+ }
.setNegativeButton(android.R.string.no, null)
.show()
} else {
@@ -186,4 +184,4 @@ class ColorSchemeActivity : BaseCustomizeActivity() {
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/customize/CustomizeActivity.kt b/app/src/main/java/io/neoterm/ui/customize/CustomizeActivity.kt
index 1d45e2e..3733bd8 100644
--- a/app/src/main/java/io/neoterm/ui/customize/CustomizeActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/customize/CustomizeActivity.kt
@@ -9,10 +9,10 @@ import android.widget.ArrayAdapter
import android.widget.Spinner
import android.widget.Toast
import io.neoterm.R
+import io.neoterm.component.ComponentManager
import io.neoterm.component.colorscheme.ColorSchemeComponent
+import io.neoterm.component.config.NeoTermPath
import io.neoterm.component.font.FontComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoTermPath
import io.neoterm.utils.getPathOfMediaUri
import java.io.File
import java.nio.file.Files
@@ -150,4 +150,4 @@ class CustomizeActivity : BaseCustomizeActivity() {
}
return super.onOptionsItemSelected(item)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/customize/adapter/ColorItemAdapter.kt b/app/src/main/java/io/neoterm/ui/customize/adapter/ColorItemAdapter.kt
deleted file mode 100644
index 7359d16..0000000
--- a/app/src/main/java/io/neoterm/ui/customize/adapter/ColorItemAdapter.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-package io.neoterm.ui.customize.adapter
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
-import io.neoterm.R
-import io.neoterm.component.colorscheme.NeoColorScheme
-import io.neoterm.ui.customize.adapter.holder.ColorItemViewHolder
-import io.neoterm.ui.customize.model.ColorItem
-
-/**
- * @author kiva
- */
-class ColorItemAdapter(
- context: Context,
- initColorScheme: NeoColorScheme,
- comparator: Comparator,
- private val listener: ColorItemAdapter.Listener
-) : SortedListAdapter(context, ColorItem::class.java, comparator), FastScrollRecyclerView.SectionedAdapter {
-
- val colorList = mutableListOf()
-
- init {
- (NeoColorScheme.COLOR_TYPE_BEGIN..NeoColorScheme.COLOR_TYPE_END)
- .forEach {
- colorList.add(ColorItem(it, initColorScheme.getColor(it) ?: ""))
- }
- edit().add(colorList).commit()
- }
-
- interface Listener {
- fun onModelClicked(model: ColorItem)
- }
-
- override fun getSectionName(position: Int): String {
- return colorList[position].colorName[0].toString()
- }
-
- override fun onCreateViewHolder(
- inflater: LayoutInflater,
- parent: ViewGroup,
- viewType: Int
- ): SortedListAdapter.ViewHolder {
- val rootView = inflater.inflate(R.layout.item_color, parent, false)
- return ColorItemViewHolder(rootView, listener)
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/customize/adapter/holder/ColorItemViewHolder.kt b/app/src/main/java/io/neoterm/ui/customize/adapter/holder/ColorItemViewHolder.kt
deleted file mode 100644
index 4e8e0ad..0000000
--- a/app/src/main/java/io/neoterm/ui/customize/adapter/holder/ColorItemViewHolder.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.neoterm.ui.customize.adapter.holder
-
-import android.view.View
-import android.widget.TextView
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-import io.neoterm.R
-import io.neoterm.backend.TerminalColors
-import io.neoterm.ui.customize.adapter.ColorItemAdapter
-import io.neoterm.ui.customize.model.ColorItem
-
-class ColorItemViewHolder(private val rootView: View, private val listener: ColorItemAdapter.Listener) :
- SortedListAdapter.ViewHolder(rootView) {
- private val colorItemName: TextView = rootView.findViewById(R.id.color_item_name)
- private val colorItemDesc: TextView = rootView.findViewById(R.id.color_item_description)
- private val colorView: View = rootView.findViewById(R.id.color_item_view)
-
- override fun performBind(item: ColorItem) {
- rootView.setOnClickListener { listener.onModelClicked(item) }
- colorItemName.text = item.colorName
- colorItemDesc.text = item.colorValue
- if (item.colorValue.isNotEmpty()) {
- val color = TerminalColors.parse(item.colorValue)
- colorView.setBackgroundColor(color)
- colorItemDesc.setTextColor(color)
- }
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/customize/model.kt b/app/src/main/java/io/neoterm/ui/customize/model.kt
new file mode 100644
index 0000000..f94e175
--- /dev/null
+++ b/app/src/main/java/io/neoterm/ui/customize/model.kt
@@ -0,0 +1,90 @@
+package io.neoterm.ui.customize
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
+import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
+import io.neoterm.App
+import io.neoterm.R
+import io.neoterm.backend.TerminalColors
+import io.neoterm.component.colorscheme.NeoColorScheme
+
+/**
+ * @author kiva
+ */
+class ColorItem(var colorType: Int, var colorValue: String) : SortedListAdapter.ViewModel {
+ override fun isSameModelAs(t: T): Boolean {
+ if (t is ColorItem) {
+ return t.colorName == colorName
+ && t.colorValue == colorValue
+ && t.colorType == colorType
+ }
+ return false
+ }
+
+ override fun isContentTheSameAs(t: T): Boolean {
+ return isSameModelAs(t)
+ }
+
+ var colorName = App.get().resources
+ .getStringArray(R.array.color_item_names)[colorType - NeoColorScheme.COLOR_TYPE_BEGIN]
+}
+
+/**
+ * @author kiva
+ */
+class ColorItemAdapter(
+ context: Context,
+ initColorScheme: NeoColorScheme,
+ comparator: Comparator,
+ private val listener: ColorItemAdapter.Listener
+) : SortedListAdapter(context, ColorItem::class.java, comparator), FastScrollRecyclerView.SectionedAdapter {
+
+ val colorList = mutableListOf()
+
+ init {
+ (NeoColorScheme.COLOR_TYPE_BEGIN..NeoColorScheme.COLOR_TYPE_END)
+ .forEach {
+ colorList.add(ColorItem(it, initColorScheme.getColor(it) ?: ""))
+ }
+ edit().add(colorList).commit()
+ }
+
+ interface Listener {
+ fun onModelClicked(model: ColorItem)
+ }
+
+ override fun getSectionName(position: Int): String {
+ return colorList[position].colorName[0].toString()
+ }
+
+ override fun onCreateViewHolder(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ viewType: Int
+ ): ViewHolder {
+ val rootView = inflater.inflate(R.layout.item_color, parent, false)
+ return ColorItemViewHolder(rootView, listener)
+ }
+}
+
+class ColorItemViewHolder(private val rootView: View, private val listener: ColorItemAdapter.Listener) :
+ SortedListAdapter.ViewHolder(rootView) {
+ private val colorItemName: TextView = rootView.findViewById(R.id.color_item_name)
+ private val colorItemDesc: TextView = rootView.findViewById(R.id.color_item_description)
+ private val colorView: View = rootView.findViewById(R.id.color_item_view)
+
+ override fun performBind(item: ColorItem) {
+ rootView.setOnClickListener { listener.onModelClicked(item) }
+ colorItemName.text = item.colorName
+ colorItemDesc.text = item.colorValue
+ if (item.colorValue.isNotEmpty()) {
+ val color = TerminalColors.parse(item.colorValue)
+ colorView.setBackgroundColor(color)
+ colorItemDesc.setTextColor(color)
+ }
+ }
+}
diff --git a/app/src/main/java/io/neoterm/ui/customize/model/ColorItem.kt b/app/src/main/java/io/neoterm/ui/customize/model/ColorItem.kt
deleted file mode 100644
index 4d3468c..0000000
--- a/app/src/main/java/io/neoterm/ui/customize/model/ColorItem.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package io.neoterm.ui.customize.model
-
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-import io.neoterm.App
-import io.neoterm.R
-import io.neoterm.component.colorscheme.NeoColorScheme
-
-/**
- * @author kiva
- */
-class ColorItem(var colorType: Int, var colorValue: String) : SortedListAdapter.ViewModel {
- override fun isSameModelAs(t: T): Boolean {
- if (t is ColorItem) {
- return t.colorName == colorName
- && t.colorValue == colorValue
- && t.colorType == colorType
- }
- return false
- }
-
- override fun isContentTheSameAs(t: T): Boolean {
- return isSameModelAs(t)
- }
-
- var colorName = App.get().resources
- .getStringArray(R.array.color_item_names)[colorType - NeoColorScheme.COLOR_TYPE_BEGIN]
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/ui/support/AboutActivity.kt b/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
similarity index 82%
rename from app/src/main/java/io/neoterm/ui/support/AboutActivity.kt
rename to app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
index 0906a82..fd6db93 100644
--- a/app/src/main/java/io/neoterm/ui/support/AboutActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/other/AboutActivity.kt
@@ -1,4 +1,4 @@
-package io.neoterm.ui.support
+package io.neoterm.ui.other
import android.content.Intent
import android.content.pm.PackageManager
@@ -17,7 +17,6 @@ import de.psdev.licensesdialog.model.Notice
import de.psdev.licensesdialog.model.Notices
import io.neoterm.App
import io.neoterm.R
-import io.neoterm.ui.setup.SetupActivity
/**
@@ -36,14 +35,6 @@ class AboutActivity : AppCompatActivity() {
} catch (ignored: PackageManager.NameNotFoundException) {
}
- findViewById(R.id.about_developers_view).setOnClickListener {
- AlertDialog.Builder(this)
- .setTitle(R.string.about_developers_label)
- .setMessage(R.string.about_developers)
- .setPositiveButton(android.R.string.yes, null)
- .show()
- }
-
findViewById(R.id.about_licenses_view).setOnClickListener {
val notices = Notices()
notices.addNotice(
@@ -141,27 +132,12 @@ class AboutActivity : AppCompatActivity() {
openUrl("https://github.com/NeoTerm/NeoTerm")
}
- findViewById(R.id.about_donate_view).setOnClickListener {
- AlertDialog.Builder(this)
- .setTitle(R.string.support_donate_label)
- .setMessage(R.string.support_donate_dialog_text)
- .setPositiveButton(R.string.support_donate_alipay, { _, _ ->
- Donation.donateByAlipay(this, "FKX025062MBLAG6E90RYBC")
- })
- .setNeutralButton(android.R.string.no, null)
- .show()
- }
-
- findViewById(R.id.about_show_help_view).setOnClickListener {
- App.get().openHelpLink();
- }
-
findViewById(R.id.about_reset_app_view).setOnClickListener {
AlertDialog.Builder(this)
.setMessage(R.string.reset_app_warning)
- .setPositiveButton(R.string.yes, { _, _ ->
+ .setPositiveButton(R.string.yes) { _, _ ->
resetApp()
- })
+ }
.setNegativeButton(android.R.string.no, null)
.show()
}
@@ -184,4 +160,4 @@ class AboutActivity : AppCompatActivity() {
}
return super.onOptionsItemSelected(item)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/bonus/BonusActivity.kt b/app/src/main/java/io/neoterm/ui/other/BonusActivity.kt
similarity index 99%
rename from app/src/main/java/io/neoterm/ui/bonus/BonusActivity.kt
rename to app/src/main/java/io/neoterm/ui/other/BonusActivity.kt
index 517f841..0cfad4d 100644
--- a/app/src/main/java/io/neoterm/ui/bonus/BonusActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/other/BonusActivity.kt
@@ -1,4 +1,4 @@
-package io.neoterm.ui.bonus
+package io.neoterm.ui.other
import android.animation.ObjectAnimator
import android.content.res.ColorStateList
diff --git a/app/src/main/java/io/neoterm/ui/crash/CrashActivity.kt b/app/src/main/java/io/neoterm/ui/other/CrashActivity.kt
similarity index 98%
rename from app/src/main/java/io/neoterm/ui/crash/CrashActivity.kt
rename to app/src/main/java/io/neoterm/ui/other/CrashActivity.kt
index fb8afa1..d2f0414 100644
--- a/app/src/main/java/io/neoterm/ui/crash/CrashActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/other/CrashActivity.kt
@@ -1,4 +1,4 @@
-package io.neoterm.ui.crash
+package io.neoterm.ui.other
import android.os.Build
import android.os.Bundle
@@ -56,4 +56,4 @@ class CrashActivity : AppCompatActivity() {
}
return "Unknown Arch"
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt b/app/src/main/java/io/neoterm/ui/other/SetupActivity.kt
similarity index 95%
rename from app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt
rename to app/src/main/java/io/neoterm/ui/other/SetupActivity.kt
index 46babdc..7981aa0 100644
--- a/app/src/main/java/io/neoterm/ui/setup/SetupActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/other/SetupActivity.kt
@@ -1,4 +1,4 @@
-package io.neoterm.ui.setup
+package io.neoterm.ui.other
import android.content.ActivityNotFoundException
import android.content.Intent
@@ -11,14 +11,9 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import io.neoterm.App
import io.neoterm.R
+import io.neoterm.component.config.NeoTermPath
import io.neoterm.component.pm.SourceHelper
-import io.neoterm.frontend.config.NeoTermPath
-import io.neoterm.setup.ResultListener
-import io.neoterm.setup.SetupHelper
-import io.neoterm.setup.SourceConnection
-import io.neoterm.setup.connections.BackupFileConnection
-import io.neoterm.setup.connections.LocalFileConnection
-import io.neoterm.setup.connections.NetworkConnection
+import io.neoterm.setup.*
import io.neoterm.utils.getPathOfMediaUri
import io.neoterm.utils.runApt
import java.io.File
diff --git a/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt b/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
index d8e7895..671dae0 100644
--- a/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/pm/PackageManagerActivity.kt
@@ -16,12 +16,10 @@ import androidx.core.view.MenuItemCompat
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
import io.neoterm.R
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoPreference
import io.neoterm.component.pm.*
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.ui.pm.adapter.PackageAdapter
-import io.neoterm.ui.pm.model.PackageModel
-import io.neoterm.ui.pm.utils.StringDistance
+import io.neoterm.utils.StringDistance
import io.neoterm.utils.runApt
import java.util.*
diff --git a/app/src/main/java/io/neoterm/ui/pm/adapter/PackageAdapter.kt b/app/src/main/java/io/neoterm/ui/pm/adapter/PackageAdapter.kt
deleted file mode 100755
index 2086640..0000000
--- a/app/src/main/java/io/neoterm/ui/pm/adapter/PackageAdapter.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.neoterm.ui.pm.adapter
-
-import android.content.Context
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
-import io.neoterm.R
-import io.neoterm.ui.pm.adapter.holder.PackageViewHolder
-import io.neoterm.ui.pm.model.PackageModel
-
-class PackageAdapter(
- context: Context,
- comparator: Comparator,
- private val listener: PackageAdapter.Listener
-) : SortedListAdapter(context, PackageModel::class.java, comparator),
- FastScrollRecyclerView.SectionedAdapter {
-
- override fun getSectionName(position: Int): String {
- return getItem(position).packageInfo.packageName?.substring(0, 1) ?: "#"
- }
-
- interface Listener {
- fun onModelClicked(model: PackageModel)
- }
-
- override fun onCreateViewHolder(
- inflater: LayoutInflater,
- parent: ViewGroup,
- viewType: Int
- ): SortedListAdapter.ViewHolder {
- val rootView = inflater.inflate(R.layout.item_package, parent, false)
- return PackageViewHolder(rootView, listener)
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/pm/adapter/holder/PackageViewHolder.kt b/app/src/main/java/io/neoterm/ui/pm/adapter/holder/PackageViewHolder.kt
deleted file mode 100755
index a17a130..0000000
--- a/app/src/main/java/io/neoterm/ui/pm/adapter/holder/PackageViewHolder.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package io.neoterm.ui.pm.adapter.holder
-
-import android.view.View
-import android.widget.TextView
-
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-
-import io.neoterm.R
-import io.neoterm.ui.pm.adapter.PackageAdapter
-import io.neoterm.ui.pm.model.PackageModel
-
-class PackageViewHolder(private val rootView: View, private val listener: PackageAdapter.Listener) :
- SortedListAdapter.ViewHolder(rootView) {
- private val packageNameView: TextView = rootView.findViewById(R.id.package_item_name)
- private val packageDescView: TextView = rootView.findViewById(R.id.package_item_desc)
-
- override fun performBind(item: PackageModel) {
- rootView.setOnClickListener { listener.onModelClicked(item) }
- packageNameView.text = item.packageInfo.packageName
- packageDescView.text = item.packageInfo.description
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/pm/model.kt b/app/src/main/java/io/neoterm/ui/pm/model.kt
new file mode 100644
index 0000000..bc0b832
--- /dev/null
+++ b/app/src/main/java/io/neoterm/ui/pm/model.kt
@@ -0,0 +1,76 @@
+package io.neoterm.ui.pm
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
+import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView
+import io.neoterm.R
+import io.neoterm.component.pm.NeoPackageInfo
+import io.neoterm.utils.formatSizeInKB
+
+class PackageAdapter(
+ context: Context,
+ comparator: Comparator,
+ private val listener: PackageAdapter.Listener
+) : SortedListAdapter(context, PackageModel::class.java, comparator),
+ FastScrollRecyclerView.SectionedAdapter {
+
+ override fun getSectionName(position: Int): String {
+ return getItem(position).packageInfo.packageName?.substring(0, 1) ?: "#"
+ }
+
+ interface Listener {
+ fun onModelClicked(model: PackageModel)
+ }
+
+ override fun onCreateViewHolder(
+ inflater: LayoutInflater,
+ parent: ViewGroup,
+ viewType: Int
+ ): ViewHolder {
+ val rootView = inflater.inflate(R.layout.item_package, parent, false)
+ return PackageViewHolder(rootView, listener)
+ }
+}
+
+class PackageViewHolder(private val rootView: View, private val listener: PackageAdapter.Listener) :
+ SortedListAdapter.ViewHolder(rootView) {
+ private val packageNameView: TextView = rootView.findViewById(R.id.package_item_name)
+ private val packageDescView: TextView = rootView.findViewById(R.id.package_item_desc)
+
+ override fun performBind(item: PackageModel) {
+ rootView.setOnClickListener { listener.onModelClicked(item) }
+ packageNameView.text = item.packageInfo.packageName
+ packageDescView.text = item.packageInfo.description
+ }
+}
+
+/**
+ * @author kiva
+ */
+
+class PackageModel(val packageInfo: NeoPackageInfo) : SortedListAdapter.ViewModel {
+ override fun isSameModelAs(t: T): Boolean {
+ if (t is PackageModel) {
+ return t.packageInfo.packageName == packageInfo.packageName
+ }
+ return false
+ }
+
+ override fun isContentTheSameAs(t: T): Boolean {
+ return isSameModelAs(t)
+ }
+
+ fun getPackageDetails(context: Context): String {
+ return context.getString(
+ R.string.package_details,
+ packageInfo.packageName, packageInfo.version,
+ packageInfo.dependenciesString,
+ packageInfo.installedSizeInBytes.formatSizeInKB(),
+ packageInfo.description, packageInfo.homePage
+ )
+ }
+}
diff --git a/app/src/main/java/io/neoterm/ui/pm/model/PackageModel.kt b/app/src/main/java/io/neoterm/ui/pm/model/PackageModel.kt
deleted file mode 100644
index a52704e..0000000
--- a/app/src/main/java/io/neoterm/ui/pm/model/PackageModel.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.neoterm.ui.pm.model
-
-import android.content.Context
-import com.github.wrdlbrnft.sortedlistadapter.SortedListAdapter
-import io.neoterm.R
-
-import io.neoterm.component.pm.NeoPackageInfo
-import io.neoterm.utils.formatSizeInKB
-
-/**
- * @author kiva
- */
-
-class PackageModel(val packageInfo: NeoPackageInfo) : SortedListAdapter.ViewModel {
- override fun isSameModelAs(t: T): Boolean {
- if (t is PackageModel) {
- return t.packageInfo.packageName == packageInfo.packageName
- }
- return false
- }
-
- override fun isContentTheSameAs(t: T): Boolean {
- return isSameModelAs(t)
- }
-
- fun getPackageDetails(context: Context): String {
- return context.getString(
- R.string.package_details,
- packageInfo.packageName, packageInfo.version,
- packageInfo.dependenciesString,
- packageInfo.installedSizeInBytes.formatSizeInKB(),
- packageInfo.description, packageInfo.homePage
- )
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/settings/GeneralSettingsActivity.kt b/app/src/main/java/io/neoterm/ui/settings/GeneralSettingsActivity.kt
index 37c1082..0a2156d 100644
--- a/app/src/main/java/io/neoterm/ui/settings/GeneralSettingsActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/settings/GeneralSettingsActivity.kt
@@ -4,7 +4,7 @@ import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import io.neoterm.R
-import io.neoterm.frontend.config.NeoPreference
+import io.neoterm.component.config.NeoPreference
import io.neoterm.utils.runApt
/**
@@ -56,4 +56,4 @@ class GeneralSettingsActivity : BasePreferenceActivity() {
}
return super.onOptionsItemSelected(item)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/support/Donation.kt b/app/src/main/java/io/neoterm/ui/support/Donation.kt
deleted file mode 100644
index 8e0eb58..0000000
--- a/app/src/main/java/io/neoterm/ui/support/Donation.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-package io.neoterm.ui.support
-
-import android.content.ActivityNotFoundException
-import android.content.Intent
-import androidx.appcompat.app.AppCompatActivity
-import java.net.URISyntaxException
-
-object Donation {
- // 旧版支付宝二维码通用 Intent Scheme Url 格式
- private val INTENT_URL_FORMAT = "intent://platformapi/startapp?saId=10000007&" +
- "clientVersion=3.7.0.0718&qrcode=https%3A%2F%2Fqr.alipay.com%2F{payCode}%3F_s" +
- "%3Dweb-other&_t=1472443966571#Intent;" +
- "scheme=alipayqr;package=com.eg.android.AlipayGphone;end"
-
- fun donateByAlipay(activity: AppCompatActivity, payCode: String): Boolean {
- return startIntentUrl(activity, INTENT_URL_FORMAT.replace("{payCode}", payCode))
- }
-
- private fun startIntentUrl(activity: AppCompatActivity, intentFullUrl: String): Boolean {
- return try {
- val intent = Intent.parseUri(
- intentFullUrl,
- Intent.URI_INTENT_SCHEME
- )
- activity.startActivity(intent)
- true
- } catch (e: URISyntaxException) {
- e.printStackTrace()
- false
- } catch (e: ActivityNotFoundException) {
- e.printStackTrace()
- false
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/ui/support/HelpActivity.kt b/app/src/main/java/io/neoterm/ui/support/HelpActivity.kt
deleted file mode 100644
index a4adbe9..0000000
--- a/app/src/main/java/io/neoterm/ui/support/HelpActivity.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package io.neoterm.ui.support
-
-import android.os.Bundle
-import android.view.MenuItem
-import androidx.appcompat.app.AppCompatActivity
-import io.neoterm.R
-
-/**
- * @author kiva
- */
-class HelpActivity : AppCompatActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.ui_faq)
- setSupportActionBar(findViewById(R.id.faq_toolbar))
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- }
-
- override fun onOptionsItemSelected(item: MenuItem?): Boolean {
- when (item?.itemId) {
- android.R.id.home ->
- finish()
- }
- return super.onOptionsItemSelected(item)
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt b/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt
index 9962804..acdc9cc 100644
--- a/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt
+++ b/app/src/main/java/io/neoterm/ui/term/NeoTermActivity.kt
@@ -23,27 +23,21 @@ import io.neoterm.App
import io.neoterm.BuildConfig
import io.neoterm.R
import io.neoterm.backend.TerminalSession
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoPreference
import io.neoterm.component.profile.ProfileComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPermission
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.shell.ShellProfile
-import io.neoterm.frontend.session.shell.client.TermSessionCallback
-import io.neoterm.frontend.session.shell.client.TermViewClient
-import io.neoterm.frontend.session.shell.client.event.*
-import io.neoterm.frontend.session.xorg.XParameter
-import io.neoterm.frontend.session.xorg.XSession
+import io.neoterm.component.session.ShellParameter
+import io.neoterm.component.session.ShellProfile
+import io.neoterm.component.session.XParameter
+import io.neoterm.component.session.XSession
+import io.neoterm.frontend.session.terminal.*
import io.neoterm.services.NeoTermService
import io.neoterm.setup.SetupHelper
+import io.neoterm.ui.other.SetupActivity
import io.neoterm.ui.pm.PackageManagerActivity
import io.neoterm.ui.settings.SettingActivity
-import io.neoterm.ui.setup.SetupActivity
-import io.neoterm.ui.term.tab.NeoTab
-import io.neoterm.ui.term.tab.NeoTabDecorator
-import io.neoterm.ui.term.tab.TermTab
-import io.neoterm.ui.term.tab.XSessionTab
import io.neoterm.utils.FullScreenHelper
+import io.neoterm.utils.NeoPermission
import io.neoterm.utils.RangedInt
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
diff --git a/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
index 4a96dbe..05a39da 100644
--- a/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
+++ b/app/src/main/java/io/neoterm/ui/term/NeoTermRemoteInterface.kt
@@ -14,12 +14,12 @@ import io.neoterm.App
import io.neoterm.R
import io.neoterm.bridge.Bridge.*
import io.neoterm.bridge.SessionId
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.session.ShellParameter
import io.neoterm.component.userscript.UserScript
import io.neoterm.component.userscript.UserScriptComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.shell.client.TermSessionCallback
+import io.neoterm.frontend.session.terminal.TermSessionCallback
import io.neoterm.services.NeoTermService
import io.neoterm.utils.Terminals
import io.neoterm.utils.getPathOfMediaUri
@@ -116,8 +116,8 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
private fun handleUserScript() {
val filesToHandle = mutableListOf()
- val userScriptService = ComponentManager.getComponent()
- val userScripts = userScriptService.userScripts
+ val comp = ComponentManager.getComponent()
+ val userScripts = comp.userScripts
if (userScripts.isEmpty()) {
App.get().errorDialog(this, R.string.no_user_script_found, { finish() })
return
@@ -241,4 +241,4 @@ class NeoTermRemoteInterface : AppCompatActivity(), ServiceConnection {
private fun detectSystemShell(): Boolean {
return false
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/term/SessionRemover.kt b/app/src/main/java/io/neoterm/ui/term/SessionRemover.kt
index d8686d2..801c73e 100644
--- a/app/src/main/java/io/neoterm/ui/term/SessionRemover.kt
+++ b/app/src/main/java/io/neoterm/ui/term/SessionRemover.kt
@@ -1,10 +1,8 @@
package io.neoterm.ui.term
import io.neoterm.backend.TerminalSession
-import io.neoterm.frontend.session.xorg.XSession
+import io.neoterm.component.session.XSession
import io.neoterm.services.NeoTermService
-import io.neoterm.ui.term.tab.TermTab
-import io.neoterm.ui.term.tab.XSessionTab
/**
* @author kiva
diff --git a/app/src/main/java/io/neoterm/ui/term/tab/NeoTab.kt b/app/src/main/java/io/neoterm/ui/term/tab/NeoTab.kt
deleted file mode 100644
index 7f8a16a..0000000
--- a/app/src/main/java/io/neoterm/ui/term/tab/NeoTab.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.neoterm.ui.term.tab
-
-import android.content.res.Configuration
-import de.mrapp.android.tabswitcher.Tab
-
-/**
- * @author kiva
- */
-open class NeoTab(title: CharSequence) : Tab(title) {
- open fun onPause() {}
-
- open fun onResume() {}
-
- open fun onStart() {}
-
- open fun onStop() {}
-
- open fun onWindowFocusChanged(hasFocus: Boolean) {}
-
- open fun onDestroy() {}
-
- open fun onConfigurationChanged(newConfig: Configuration) {}
-}
\ No newline at end of file
diff --git a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt b/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt
deleted file mode 100644
index debaed9..0000000
--- a/app/src/main/java/io/neoterm/ui/term/tab/TermTab.kt
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.neoterm.ui.term.tab
-
-import android.content.Context
-import android.view.inputmethod.InputMethodManager
-import androidx.appcompat.widget.Toolbar
-import io.neoterm.component.colorscheme.ColorSchemeComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.session.shell.client.TermSessionData
-import io.neoterm.frontend.session.shell.client.TermUiPresenter
-import io.neoterm.frontend.session.shell.client.event.*
-import org.greenrobot.eventbus.EventBus
-
-/**
- * @author kiva
- */
-
-class TermTab(title: CharSequence) : NeoTab(title), TermUiPresenter {
- companion object {
- val PARAMETER_SHOW_EKS = "show_eks"
- }
-
- var termData = TermSessionData()
- var toolbar: Toolbar? = null
-
- fun updateColorScheme() {
- val colorSchemeManager = ComponentManager.getComponent()
- colorSchemeManager.applyColorScheme(
- termData.termView, termData.extraKeysView,
- colorSchemeManager.getCurrentColorScheme()
- )
- }
-
- fun cleanup() {
- termData.cleanup()
- toolbar = null
- }
-
- fun onFullScreenModeChanged(fullScreen: Boolean) {
- // Window token changed, we need to recreate PopupWindow
- resetAutoCompleteStatus()
- }
-
- override fun requireHideIme() {
- val terminalView = termData.termView
- if (terminalView != null) {
- val imm = terminalView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
- if (imm.isActive) {
- imm.hideSoftInputFromWindow(terminalView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
- }
- }
- }
-
- override fun requireFinishAutoCompletion(): Boolean {
- return termData.onAutoCompleteListener?.onFinishCompletion() ?: false
- }
-
- override fun requireToggleFullScreen() {
- EventBus.getDefault().post(ToggleFullScreenEvent())
- }
-
- override fun requirePaste() {
- termData.termView?.pasteFromClipboard()
- }
-
- override fun requireClose() {
- requireHideIme()
- EventBus.getDefault().post(TabCloseEvent(this))
- }
-
- override fun requireUpdateTitle(title: String?) {
- if (title != null && title.isNotEmpty()) {
- this.title = title
- EventBus.getDefault().post(TitleChangedEvent(title))
- termData.viewClient?.updateExtraKeys(title)
- }
- }
-
- override fun requireOnSessionFinished() {
- // do nothing
- }
-
- override fun requireCreateNew() {
- EventBus.getDefault().post(CreateNewSessionEvent())
- }
-
- override fun requireSwitchToPrevious() {
- EventBus.getDefault().post(SwitchSessionEvent(toNext = false))
- }
-
- override fun requireSwitchToNext() {
- EventBus.getDefault().post(SwitchSessionEvent(toNext = true))
- }
-
- override fun requireSwitchTo(index: Int) {
- EventBus.getDefault().post(SwitchIndexedSessionEvent(index))
- }
-
- fun resetAutoCompleteStatus() {
- termData.onAutoCompleteListener?.onCleanUp()
- termData.onAutoCompleteListener = null
- }
-
- fun resetStatus() {
- resetAutoCompleteStatus()
- termData.extraKeysView?.updateButtons()
- termData.termView?.updateSize()
- termData.termView?.onScreenUpdated()
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/term/tab/XSessionTab.kt b/app/src/main/java/io/neoterm/ui/term/tab/XSessionTab.kt
deleted file mode 100644
index dbf3257..0000000
--- a/app/src/main/java/io/neoterm/ui/term/tab/XSessionTab.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-package io.neoterm.ui.term.tab
-
-import android.content.res.Configuration
-import io.neoterm.frontend.session.xorg.XSession
-
-/**
- * @author kiva
- */
-class XSessionTab(title: CharSequence) : NeoTab(title) {
- var session: XSession? = null
- val sessionData
- get() = session?.mSessionData
-
- override fun onWindowFocusChanged(hasFocus: Boolean) {
- super.onWindowFocusChanged(hasFocus)
- if (!hasFocus) {
- onPause()
- } else {
- onResume()
- }
- }
-
- override fun onConfigurationChanged(newConfig: Configuration) {
- super.onConfigurationChanged(newConfig)
- session?.updateScreenOrientation()
- }
-
- override fun onPause() {
- session?.onPause()
- super.onPause()
- }
-
- override fun onDestroy() {
- super.onDestroy()
- session?.onDestroy()
- }
-
- override fun onResume() {
- super.onResume()
- session?.onResume()
- }
-}
diff --git a/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt b/app/src/main/java/io/neoterm/ui/term/tabs.kt
similarity index 53%
rename from app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt
rename to app/src/main/java/io/neoterm/ui/term/tabs.kt
index 3644998..db7988a 100644
--- a/app/src/main/java/io/neoterm/ui/term/tab/NeoTabDecorator.kt
+++ b/app/src/main/java/io/neoterm/ui/term/tabs.kt
@@ -1,33 +1,46 @@
-package io.neoterm.ui.term.tab
+package io.neoterm.ui.term
import android.content.Context
+import android.content.res.Configuration
import android.graphics.Rect
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.view.inputmethod.InputMethodManager
import android.widget.FrameLayout
+import androidx.appcompat.widget.Toolbar
import de.mrapp.android.tabswitcher.Tab
import de.mrapp.android.tabswitcher.TabSwitcher
import de.mrapp.android.tabswitcher.TabSwitcherDecorator
-import io.neoterm.Globals
import io.neoterm.NeoGLView
import io.neoterm.R
+import io.neoterm.component.ComponentManager
import io.neoterm.component.colorscheme.ColorSchemeComponent
-import io.neoterm.frontend.completion.listener.OnAutoCompleteListener
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.DefaultValues
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.session.shell.client.TermCompleteListener
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
-import io.neoterm.ui.term.NeoTermActivity
+import io.neoterm.component.completion.OnAutoCompleteListener
+import io.neoterm.component.config.DefaultValues
+import io.neoterm.component.config.NeoPreference
+import io.neoterm.component.session.XSession
+import io.neoterm.frontend.session.terminal.*
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
import io.neoterm.utils.Terminals
+import org.greenrobot.eventbus.EventBus
/**
* @author kiva
*/
+open class NeoTab(title: CharSequence) : Tab(title) {
+ open fun onPause() {}
+ open fun onResume() {}
+ open fun onStart() {}
+ open fun onStop() {}
+ open fun onWindowFocusChanged(hasFocus: Boolean) {}
+ open fun onDestroy() {}
+ open fun onConfigurationChanged(newConfig: Configuration) {}
+}
+
class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
companion object {
private var VIEW_TYPE_COUNT = 0
@@ -124,20 +137,16 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
)
)
- if (Globals.HideSystemMousePointer
- && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N
- ) {
- sessionData.glView?.pointerIcon =
- android.view.PointerIcon.getSystemIcon(
- context,
- android.view.PointerIcon.TYPE_NULL
- )
- }
+ sessionData.glView?.pointerIcon =
+ android.view.PointerIcon.getSystemIcon(
+ context,
+ android.view.PointerIcon.TYPE_NULL
+ )
val r = Rect()
videoLayout.getWindowVisibleDisplayFrame(r)
sessionData.glView?.callNativeScreenVisibleRect(r.left, r.top, r.right, r.bottom)
- videoLayout.viewTreeObserver.addOnGlobalLayoutListener({
+ videoLayout.viewTreeObserver.addOnGlobalLayoutListener {
val r = Rect()
videoLayout.getWindowVisibleDisplayFrame(r)
val heightDiff = videoLayout.rootView.height - videoLayout.height // Take system bar into consideration
@@ -146,23 +155,29 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
"SDL",
"Main window visible region changed: " + r.left + ":" + r.top + ":" + r.width() + ":" + r.height()
)
- videoLayout.postDelayed({
- sessionData.glView?.callNativeScreenVisibleRect(
- r.left + widthDiff,
- r.top + heightDiff,
- r.width(),
- r.height()
- )
- }, 300)
- videoLayout.postDelayed({
- sessionData.glView?.callNativeScreenVisibleRect(
- r.left + widthDiff,
- r.top + heightDiff,
- r.width(),
- r.height()
- )
- }, 600)
- })
+ videoLayout.postDelayed(
+ {
+ sessionData.glView?.callNativeScreenVisibleRect(
+ r.left + widthDiff,
+ r.top + heightDiff,
+ r.width(),
+ r.height()
+ )
+ },
+ 300
+ )
+ videoLayout.postDelayed(
+ {
+ sessionData.glView?.callNativeScreenVisibleRect(
+ r.left + widthDiff,
+ r.top + heightDiff,
+ r.width(),
+ r.height()
+ )
+ },
+ 600
+ )
+ }
}
}.start()
}
@@ -208,4 +223,133 @@ class NeoTabDecorator(val context: NeoTermActivity) : TabSwitcherDecorator() {
}
return -1
}
-}
\ No newline at end of file
+}
+
+class XSessionTab(title: CharSequence) : NeoTab(title) {
+ var session: XSession? = null
+ val sessionData
+ get() = session?.mSessionData
+
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ super.onWindowFocusChanged(hasFocus)
+ if (!hasFocus) {
+ onPause()
+ } else {
+ onResume()
+ }
+ }
+
+ override fun onConfigurationChanged(newConfig: Configuration) {
+ super.onConfigurationChanged(newConfig)
+ session?.updateScreenOrientation()
+ }
+
+ override fun onPause() {
+ session?.onPause()
+ super.onPause()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ session?.onDestroy()
+ }
+
+ override fun onResume() {
+ super.onResume()
+ session?.onResume()
+ }
+}
+
+class TermTab(title: CharSequence) : NeoTab(title), TermUiPresenter {
+ companion object {
+ val PARAMETER_SHOW_EKS = "show_eks"
+ }
+
+ var termData = TermSessionData()
+ var toolbar: Toolbar? = null
+
+ fun updateColorScheme() {
+ val colorSchemeManager = ComponentManager.getComponent()
+ colorSchemeManager.applyColorScheme(
+ termData.termView, termData.extraKeysView,
+ colorSchemeManager.getCurrentColorScheme()
+ )
+ }
+
+ fun cleanup() {
+ termData.cleanup()
+ toolbar = null
+ }
+
+ fun onFullScreenModeChanged(fullScreen: Boolean) {
+ // Window token changed, we need to recreate PopupWindow
+ resetAutoCompleteStatus()
+ }
+
+ override fun requireHideIme() {
+ val terminalView = termData.termView
+ if (terminalView != null) {
+ val imm = terminalView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
+ if (imm.isActive) {
+ imm.hideSoftInputFromWindow(terminalView.windowToken, InputMethodManager.HIDE_NOT_ALWAYS)
+ }
+ }
+ }
+
+ override fun requireFinishAutoCompletion(): Boolean {
+ return termData.onAutoCompleteListener?.onFinishCompletion() ?: false
+ }
+
+ override fun requireToggleFullScreen() {
+ EventBus.getDefault().post(ToggleFullScreenEvent())
+ }
+
+ override fun requirePaste() {
+ termData.termView?.pasteFromClipboard()
+ }
+
+ override fun requireClose() {
+ requireHideIme()
+ EventBus.getDefault().post(TabCloseEvent(this))
+ }
+
+ override fun requireUpdateTitle(title: String?) {
+ if (title != null && title.isNotEmpty()) {
+ this.title = title
+ EventBus.getDefault().post(TitleChangedEvent(title))
+ termData.viewClient?.updateExtraKeys(title)
+ }
+ }
+
+ override fun requireOnSessionFinished() {
+ // do nothing
+ }
+
+ override fun requireCreateNew() {
+ EventBus.getDefault().post(CreateNewSessionEvent())
+ }
+
+ override fun requireSwitchToPrevious() {
+ EventBus.getDefault().post(SwitchSessionEvent(toNext = false))
+ }
+
+ override fun requireSwitchToNext() {
+ EventBus.getDefault().post(SwitchSessionEvent(toNext = true))
+ }
+
+ override fun requireSwitchTo(index: Int) {
+ EventBus.getDefault().post(SwitchIndexedSessionEvent(index))
+ }
+
+ fun resetAutoCompleteStatus() {
+ termData.onAutoCompleteListener?.onCleanUp()
+ termData.onAutoCompleteListener = null
+ }
+
+ fun resetStatus() {
+ resetAutoCompleteStatus()
+ termData.extraKeysView?.updateButtons()
+ termData.termView?.updateSize()
+ termData.termView?.onScreenUpdated()
+ }
+}
diff --git a/app/src/main/java/io/neoterm/utils/CrashHandler.kt b/app/src/main/java/io/neoterm/utils/CrashHandler.kt
index f54f249..4d4397c 100644
--- a/app/src/main/java/io/neoterm/utils/CrashHandler.kt
+++ b/app/src/main/java/io/neoterm/utils/CrashHandler.kt
@@ -2,7 +2,7 @@ package io.neoterm.utils
import android.content.Intent
import io.neoterm.App
-import io.neoterm.ui.crash.CrashActivity
+import io.neoterm.ui.other.CrashActivity
/**
* @author kiva
diff --git a/app/src/main/java/io/neoterm/frontend/logging/NLog.kt b/app/src/main/java/io/neoterm/utils/NLog.kt
similarity index 99%
rename from app/src/main/java/io/neoterm/frontend/logging/NLog.kt
rename to app/src/main/java/io/neoterm/utils/NLog.kt
index 13c8d18..bca8ffd 100644
--- a/app/src/main/java/io/neoterm/frontend/logging/NLog.kt
+++ b/app/src/main/java/io/neoterm/utils/NLog.kt
@@ -1,4 +1,4 @@
-package io.neoterm.frontend.logging
+package io.neoterm.utils
import android.content.Context
import android.util.Log
diff --git a/app/src/main/java/io/neoterm/frontend/config/NeoPermission.kt b/app/src/main/java/io/neoterm/utils/NeoPermission.kt
similarity index 91%
rename from app/src/main/java/io/neoterm/frontend/config/NeoPermission.kt
rename to app/src/main/java/io/neoterm/utils/NeoPermission.kt
index d8c7f46..b89ccfe 100644
--- a/app/src/main/java/io/neoterm/frontend/config/NeoPermission.kt
+++ b/app/src/main/java/io/neoterm/utils/NeoPermission.kt
@@ -1,10 +1,9 @@
-package io.neoterm.frontend.config
+package io.neoterm.utils
import android.Manifest
import android.content.ActivityNotFoundException
import android.content.DialogInterface
import android.content.pm.PackageManager
-import android.os.Build
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
@@ -17,10 +16,6 @@ object NeoPermission {
const val REQUEST_APP_PERMISSION = 10086
fun initAppPermission(context: AppCompatActivity, requestCode: Int) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
- return
- }
-
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_EXTERNAL_STORAGE
@@ -56,4 +51,4 @@ object NeoPermission {
// for MIUI, we ignore it.
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/ui/pm/utils/StringDistance.java b/app/src/main/java/io/neoterm/utils/StringDistance.java
similarity index 82%
rename from app/src/main/java/io/neoterm/ui/pm/utils/StringDistance.java
rename to app/src/main/java/io/neoterm/utils/StringDistance.java
index 27e9a95..b55415c 100644
--- a/app/src/main/java/io/neoterm/ui/pm/utils/StringDistance.java
+++ b/app/src/main/java/io/neoterm/utils/StringDistance.java
@@ -1,4 +1,4 @@
-package io.neoterm.ui.pm.utils;
+package io.neoterm.utils;
/**
* @author kiva
@@ -27,9 +27,7 @@ public class StringDistance {
int insert = d[i][j - 1] + 1;
int delete = d[i - 1][j] + 1;
int replace = d[i - 1][j - 1] + 1;
- d[i][j] = Math.min(insert, delete) > Math.min(delete, replace)
- ? Math.min(delete, replace)
- : Math.min(insert, delete);
+ d[i][j] = Math.min(Math.min(insert, delete), Math.min(delete, replace));
}
}
}
diff --git a/app/src/main/java/io/neoterm/utils/Terminals.kt b/app/src/main/java/io/neoterm/utils/Terminals.kt
index 2a44c87..77e9be2 100644
--- a/app/src/main/java/io/neoterm/utils/Terminals.kt
+++ b/app/src/main/java/io/neoterm/utils/Terminals.kt
@@ -3,16 +3,16 @@ package io.neoterm.utils
import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import io.neoterm.backend.TerminalSession
+import io.neoterm.component.ComponentManager
+import io.neoterm.component.config.NeoPreference
import io.neoterm.component.font.FontComponent
import io.neoterm.component.session.SessionComponent
-import io.neoterm.frontend.component.ComponentManager
-import io.neoterm.frontend.config.NeoPreference
-import io.neoterm.frontend.session.shell.ShellParameter
-import io.neoterm.frontend.session.xorg.XParameter
-import io.neoterm.frontend.session.xorg.XSession
-import io.neoterm.frontend.terminal.TerminalView
-import io.neoterm.frontend.terminal.TerminalViewClient
-import io.neoterm.frontend.terminal.extrakey.ExtraKeysView
+import io.neoterm.component.session.ShellParameter
+import io.neoterm.component.session.XParameter
+import io.neoterm.component.session.XSession
+import io.neoterm.frontend.session.view.TerminalView
+import io.neoterm.frontend.session.view.TerminalViewClient
+import io.neoterm.frontend.session.view.extrakey.ExtraKeysView
/**
* @author kiva
@@ -64,4 +64,4 @@ object Terminals {
builder.append('"')
return builder.toString()
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/io/neoterm/utils/utils.kt b/app/src/main/java/io/neoterm/utils/utils.kt
index 68f762c..9d3ff94 100644
--- a/app/src/main/java/io/neoterm/utils/utils.kt
+++ b/app/src/main/java/io/neoterm/utils/utils.kt
@@ -7,7 +7,7 @@ import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import io.neoterm.R
-import io.neoterm.frontend.config.NeoTermPath
+import io.neoterm.component.config.NeoTermPath
import io.neoterm.frontend.floating.TerminalDialog
import java.nio.file.Files
import java.nio.file.Paths
diff --git a/app/src/main/res/layout/popup_auto_complete.xml b/app/src/main/res/layout/popup_auto_complete.xml
index 4bb855f..0d0e594 100644
--- a/app/src/main/res/layout/popup_auto_complete.xml
+++ b/app/src/main/res/layout/popup_auto_complete.xml
@@ -1,13 +1,13 @@
-
+
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/ui_about.xml b/app/src/main/res/layout/ui_about.xml
index b0a72ef..b9c69d6 100644
--- a/app/src/main/res/layout/ui_about.xml
+++ b/app/src/main/res/layout/ui_about.xml
@@ -105,80 +105,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/ui_color_scheme.xml b/app/src/main/res/layout/ui_color_scheme.xml
index e996733..bb2c600 100644
--- a/app/src/main/res/layout/ui_color_scheme.xml
+++ b/app/src/main/res/layout/ui_color_scheme.xml
@@ -27,7 +27,7 @@
android:layout_weight="1.0"
android:background="@color/terminal_background">
-
-
-
-
-
-
-
-