├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── nightmare │ │ │ │ └── termare │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ ├── values │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── network_security_config.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle ├── assets ├── fonts │ ├── DroidSansMono.ttf │ ├── MenloforPowerline.ttf │ ├── MesloLGMforPowerline.ttf │ ├── SourceCodePro.ttf │ ├── SourceCodeProMediumforPowerline.otf │ └── UbuntuMono.ttf ├── icons │ └── code.png ├── lib │ └── libterm.dylib ├── ogg │ └── InCallNotification.ogg └── text │ └── neofetch.txt ├── dynamic_library ├── libterm.dylib └── libterm.so ├── ios ├── .gitignore ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ └── Release.xcconfig ├── Podfile ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ └── Icon-App-83.5x83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app │ ├── modules │ │ ├── dashboard │ │ │ └── views │ │ │ │ └── dashboard.dart │ │ ├── setting │ │ │ ├── bindings │ │ │ │ └── setting_binding.dart │ │ │ ├── controllers │ │ │ │ └── setting_controller.dart │ │ │ ├── models │ │ │ │ └── models.json │ │ │ ├── models_model.dart │ │ │ ├── utils │ │ │ │ └── term_utils.dart │ │ │ └── views │ │ │ │ ├── powerlevel10k_addr.dart │ │ │ │ ├── setting_page.dart │ │ │ │ └── zsh_select_addr.dart │ │ └── terminal │ │ │ ├── bindings │ │ │ └── terminal_binding.dart │ │ │ ├── controllers │ │ │ └── terminal_controller.dart │ │ │ └── views │ │ │ ├── download_bootstrap_page.dart │ │ │ ├── quark_window_check.dart │ │ │ ├── terminal_pages.dart │ │ │ ├── terminal_title.dart │ │ │ ├── web_view.dart │ │ │ └── xterm_wrapper.dart │ ├── routes │ │ ├── app_pages.dart │ │ └── app_routes.dart │ └── widgets │ │ ├── custom_icon_button.dart │ │ ├── mac_safearea.dart │ │ ├── pop_button.dart │ │ ├── term_bottom_bar.dart │ │ ├── termare_view_with_bar.dart │ │ └── terminal_drawer.dart ├── config │ ├── assets.dart │ └── config.dart ├── main.dart ├── termare_app.dart └── themes │ ├── app_colors.dart │ ├── color_schema_extension.dart │ ├── default_theme_data.dart │ └── theme.dart ├── macos ├── .gitignore ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── app_icon_1024.png │ │ ├── app_icon_128.png │ │ ├── app_icon_16.png │ │ ├── app_icon_256.png │ │ ├── app_icon_32.png │ │ ├── app_icon_512.png │ │ └── app_icon_64.png │ ├── Base.lproj │ └── MainMenu.xib │ ├── Configs │ ├── AppInfo.xcconfig │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── Warnings.xcconfig │ ├── DebugProfile.entitlements │ ├── Info.plist │ ├── MainFlutterWindow.swift │ └── Release.entitlements ├── pubspec.lock ├── pubspec.yaml ├── screencap ├── cmatrix-r.jpg ├── cmatrix.jpg ├── dart-version.jpg ├── htop.jpg ├── mac-neofetch.png ├── nano.jpg ├── oh_my_zsh.jpg ├── select-page.jpg ├── setting-page-01.jpg ├── setting-page-02.jpg ├── sl.jpg └── vim.jpg ├── scripts ├── build_macos.sh ├── build_windows.bat ├── clean.sh ├── generate_mac_app.sh ├── patch_executable.sh ├── properties.sh ├── run_release.sh └── upload │ └── upload.sh ├── test └── widget_test.dart └── web ├── favicon.png ├── icons ├── Icon-192.png └── Icon-512.png ├── index.html └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | **/ios/Flutter/.last_build_id 26 | .dart_tool/ 27 | .flutter-plugins 28 | .flutter-plugins-dependencies 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Web related 35 | lib/generated_plugin_registrant.dart 36 | 37 | # Symbolication related 38 | app.*.symbols 39 | 40 | # Obfuscation related 41 | app.*.map.json 42 | 43 | # Android Studio will place build artifacts here 44 | /android/app/debug 45 | /android/app/profile 46 | /android/app/release 47 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 8bee0834e4be79879f15222cce8fa9642cfefb2b 8 | channel: master 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // 使用 IntelliSense 了解相关属性。 3 | // 悬停以查看现有属性的描述。 4 | // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Linux", 9 | "type": "dart", 10 | "request": "launch", 11 | "program": "lib/main.dart", 12 | "deviceId": "linux" 13 | }, 14 | { 15 | "name": "Mac Desktop", 16 | "request": "launch", 17 | "type": "dart", 18 | "deviceId": "macos" 19 | }, 20 | { 21 | "name": "Windows Desktop", 22 | "request": "launch", 23 | "type": "dart", 24 | "deviceId": "windows" 25 | }, 26 | { 27 | "name": "小米10", 28 | "request": "launch", 29 | "type": "dart", 30 | "deviceId": "Mi 10" 31 | }, 32 | { 33 | "name": "小米10s", 34 | "request": "launch", 35 | "type": "dart", 36 | "deviceId": "M2102J2SC" 37 | }, 38 | { 39 | "name": "红米K30", 40 | "request": "launch", 41 | "type": "dart", 42 | "deviceId": "Redmi K30" 43 | }, 44 | { 45 | "name": "平板", 46 | "request": "launch", 47 | "type": "dart", 48 | "deviceId": "M2105K81AC" 49 | }, 50 | ] 51 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## [1.0.0] 4 | 5 | * first upload 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Nightmare-MY 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Termare application(开源版) 2 | 3 | Termare 是一个支持多平台的本地终端模拟器,与 Termux 不同的是,支持更多的平台。 4 | 5 | 在安卓端同样有自己独立的源。 6 | 7 | > 注意目前以运行在安卓平台为主,PC端目前表现很差,还在努力开发中,不要尝试将此终端模拟器正式投入到 PC 中使用。 8 | 9 | ## 安装 10 | 11 | [termare官网](http://nightmare.fun/termarehome/): 12 | 13 | ## 开发者 14 | 15 | ### 编译 16 | 17 | 这是一个 Flutter 项目,如果你是 Flutter 开发者,仓库根目录即为工程目录,直接运行即可。Flutter 为 master 分支。 18 | 非 Flutter 开发者请移步到 [Flutter 文档](https://flutter.dev/docs),阅读 Flutter 相关的文档。 19 | 20 | ## 关联仓库 21 | 22 | ## Terminal resources 23 | 24 | - [XTerm control sequences](http://invisible-island.net/xterm/ctlseqs/ctlseqs.html) 25 | - [vt100.net](http://vt100.net/) 26 | - [Terminal codes (ANSI and terminfo equivalents)](http://wiki.bash-hackers.org/scripting/terminalcodes) 27 | 28 | ## Terminal emulators 29 | 30 | - VTE (libvte): Terminal emulator widget for GTK+, mainly used in gnome-terminal. 31 | [Source](https://github.com/GNOME/vte), [Open Issues](https://bugzilla.gnome.org/buglist.cgi?quicksearch=product%3A%22vte%22+), 32 | and [All (including closed) issues](https://bugzilla.gnome.org/buglist.cgi?bug_status=RESOLVED&bug_status=VERIFIED&chfield=resolution&chfieldfrom=-2000d&chfieldvalue=FIXED&product=vte&resolution=FIXED). 33 | 34 | - iTerm 2: OS X terminal application. [Source](https://github.com/gnachman/iTerm2), 35 | [Issues](https://gitlab.com/gnachman/iterm2/issues) and [Documentation](http://www.iterm2.com/documentation.html) 36 | (which includes [iTerm2 proprietary escape codes](http://www.iterm2.com/documentation-escape-codes.html)). 37 | 38 | - Konsole: KDE terminal application. [Source](https://projects.kde.org/projects/kde/applications/konsole/repository), 39 | in particular [tests](https://projects.kde.org/projects/kde/applications/konsole/repository/revisions/master/show/tests), 40 | [Bugs](https://bugs.kde.org/buglist.cgi?bug_severity=critical&bug_severity=grave&bug_severity=major&bug_severity=crash&bug_severity=normal&bug_severity=minor&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole) 41 | and [Wishes](https://bugs.kde.org/buglist.cgi?bug_severity=wishlist&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&product=konsole). 42 | 43 | - hterm: JavaScript terminal implementation from Chromium. [Source](https://github.com/chromium/hterm), 44 | including [tests](https://github.com/chromium/hterm/blob/master/js/hterm_vt_tests.js), 45 | and [Google group](https://groups.google.com/a/chromium.org/forum/#!forum/chromium-hterm). 46 | 47 | - xterm: The grandfather of terminal emulators. 48 | [Source](http://invisible-island.net/datafiles/release/xterm.tar.gz). 49 | 50 | - Connectbot: Android SSH client. [Source](https://github.com/connectbot/connectbot) 51 | 52 | - Android Terminal Emulator: Android terminal app which Termux terminal handling 53 | is based on. Inactive. [Source](https://github.com/jackpal/Android-Terminal-Emulator). 54 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Specify analysis options. 2 | # 3 | # Until there are meta linter rules, each desired lint must be explicitly enabled. 4 | # See: https://github.com/dart-lang/linter/issues/288 5 | # 6 | # For a list of lints, see: http://dart-lang.github.io/linter/lints/ 7 | # See the configuration guide for more 8 | # https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer 9 | # 10 | # There are other similar analysis options files in the flutter repos, 11 | # which should be kept in sync with this file: 12 | # 13 | # - analysis_options.yaml (this file) 14 | # - packages/flutter/lib/analysis_options_user.yaml 15 | # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml 16 | # - https://github.com/flutter/engine/blob/master/analysis_options.yaml 17 | # 18 | # This file contains the analysis options used by Flutter tools, such as IntelliJ, 19 | # Android Studio, and the `flutter analyze` command. 20 | 21 | analyzer: 22 | strong-mode: 23 | implicit-casts: false 24 | implicit-dynamic: true 25 | errors: 26 | # treat missing required parameters as a warning (not a hint) 27 | missing_required_param: warning 28 | # treat missing returns as a warning (not a hint) 29 | missing_return: warning 30 | # allow having TODOs in the code 31 | todo: ignore 32 | # allow self-reference to deprecated members (we do this because otherwise we have 33 | # to annotate every member in every test, assert, etc, when we deprecate something) 34 | deprecated_member_use_from_same_package: ignore 35 | # Ignore analyzer hints for updating pubspecs when using Future or 36 | # Stream and not importing dart:async 37 | # Please see https://github.com/flutter/flutter/pull/24528 for details. 38 | sdk_version_async_exported_from_core: ignore 39 | # Turned off until null-safe rollout is complete. 40 | unnecessary_null_comparison: ignore 41 | exclude: 42 | - "bin/cache/**" 43 | 44 | linter: 45 | rules: 46 | # these rules are documented on and in the same order as 47 | # the Dart Lint rules page to make maintenance easier 48 | # https://github.com/dart-lang/linter/blob/master/example/all.yaml 49 | - always_declare_return_types 50 | - always_put_control_body_on_new_line 51 | # - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219 52 | - always_require_non_null_named_parameters 53 | # - always_specify_types 54 | # - always_use_package_imports # we do this commonly 55 | - annotate_overrides 56 | # - avoid_annotating_with_dynamic # conflicts with always_specify_types 57 | - avoid_bool_literals_in_conditional_expressions 58 | # - avoid_catches_without_on_clauses # we do this commonly 59 | # - avoid_catching_errors # we do this commonly 60 | - avoid_classes_with_only_static_members 61 | # - avoid_double_and_int_checks # only useful when targeting JS runtime 62 | # - avoid_dynamic_calls # not yet tested 63 | - avoid_empty_else 64 | - avoid_equals_and_hash_code_on_mutable_classes 65 | # - avoid_escaping_inner_quotes # not yet tested 66 | - avoid_field_initializers_in_const_classes 67 | - avoid_function_literals_in_foreach_calls 68 | # - avoid_implementing_value_types # not yet tested 69 | - avoid_init_to_null 70 | # - avoid_js_rounded_ints # only useful when targeting JS runtime 71 | - avoid_null_checks_in_equality_operators 72 | # - avoid_positional_boolean_parameters # not yet tested 73 | # - avoid_print # not yet tested 74 | # - avoid_private_typedef_functions # we prefer having typedef (discussion in https://github.com/flutter/flutter/pull/16356) 75 | # - avoid_redundant_argument_values # not yet tested 76 | - avoid_relative_lib_imports 77 | - avoid_renaming_method_parameters 78 | - avoid_return_types_on_setters 79 | # - avoid_returning_null # there are plenty of valid reasons to return null 80 | # - avoid_returning_null_for_future # not yet tested 81 | - avoid_returning_null_for_void 82 | # - avoid_returning_this # there are plenty of valid reasons to return this 83 | # - avoid_setters_without_getters # not yet tested 84 | - avoid_shadowing_type_parameters 85 | - avoid_single_cascade_in_expression_statements 86 | - avoid_slow_async_io 87 | - avoid_type_to_string 88 | - avoid_types_as_parameter_names 89 | # - avoid_types_on_closure_parameters # conflicts with always_specify_types 90 | # - avoid_unnecessary_containers # not yet tested 91 | - avoid_unused_constructor_parameters 92 | - avoid_void_async 93 | # - avoid_web_libraries_in_flutter # not yet tested 94 | - await_only_futures 95 | - camel_case_extensions 96 | - camel_case_types 97 | - cancel_subscriptions 98 | # - cascade_invocations # not yet tested 99 | - cast_nullable_to_non_nullable 100 | # - close_sinks # not reliable enough 101 | # - comment_references # blocked on https://github.com/dart-lang/linter/issues/1142 102 | # - constant_identifier_names # needs an opt-out https://github.com/dart-lang/linter/issues/204 103 | - control_flow_in_finally 104 | # - curly_braces_in_flow_control_structures # not required by flutter style 105 | # - deprecated_consistency # not yet tested 106 | # - diagnostic_describe_all_properties # not yet tested 107 | - directives_ordering 108 | # - do_not_use_environment # we do this commonly 109 | - empty_catches 110 | - empty_constructor_bodies 111 | - empty_statements 112 | - exhaustive_cases 113 | - file_names 114 | - flutter_style_todos 115 | - hash_and_equals 116 | - implementation_imports 117 | # - invariant_booleans # too many false positives: https://github.com/dart-lang/linter/issues/811 118 | - iterable_contains_unrelated_type 119 | # - join_return_with_assignment # not required by flutter style 120 | - leading_newlines_in_multiline_strings 121 | - library_names 122 | - library_prefixes 123 | # - lines_longer_than_80_chars # not required by flutter style 124 | - list_remove_unrelated_type 125 | # - literal_only_boolean_expressions # too many false positives: https://github.com/dart-lang/sdk/issues/34181 126 | - missing_whitespace_between_adjacent_strings 127 | - no_adjacent_strings_in_list 128 | # - no_default_cases # too many false positives 129 | - no_duplicate_case_values 130 | - no_logic_in_create_state 131 | # - no_runtimeType_toString # ok in tests; we enable this only in packages/ 132 | - non_constant_identifier_names 133 | - null_check_on_nullable_type_parameter 134 | - null_closures 135 | # - omit_local_variable_types # opposite of always_specify_types 136 | # - one_member_abstracts # too many false positives 137 | # - only_throw_errors # https://github.com/flutter/flutter/issues/5792 138 | - overridden_fields 139 | - package_api_docs 140 | - package_names 141 | - package_prefixed_library_names 142 | # - parameter_assignments # we do this commonly 143 | - prefer_adjacent_string_concatenation 144 | - prefer_asserts_in_initializer_lists 145 | # - prefer_asserts_with_message # not required by flutter style 146 | - prefer_collection_literals 147 | - prefer_conditional_assignment 148 | - prefer_const_constructors 149 | - prefer_const_constructors_in_immutables 150 | - prefer_const_declarations 151 | - prefer_const_literals_to_create_immutables 152 | # - prefer_constructors_over_static_methods # far too many false positives 153 | - prefer_contains 154 | # - prefer_double_quotes # opposite of prefer_single_quotes 155 | - prefer_equal_for_default_values 156 | # - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods 157 | - prefer_final_fields 158 | - prefer_final_in_for_each 159 | - prefer_final_locals 160 | - prefer_for_elements_to_map_fromIterable 161 | - prefer_foreach 162 | # - prefer_function_declarations_over_variables # not yet tested 163 | - prefer_generic_function_type_aliases 164 | - prefer_if_elements_to_conditional_expressions 165 | - prefer_if_null_operators 166 | - prefer_initializing_formals 167 | - prefer_inlined_adds 168 | # - prefer_int_literals # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#use-double-literals-for-double-constants 169 | # - prefer_interpolation_to_compose_strings # doesn't work with raw strings, see https://github.com/dart-lang/linter/issues/2490 170 | - prefer_is_empty 171 | - prefer_is_not_empty 172 | - prefer_is_not_operator 173 | - prefer_iterable_whereType 174 | # - prefer_mixin # https://github.com/dart-lang/language/issues/32 175 | - prefer_null_aware_operators 176 | # - prefer_relative_imports # not yet tested 177 | - prefer_single_quotes 178 | - prefer_spread_collections 179 | - prefer_typing_uninitialized_variables 180 | - prefer_void_to_null 181 | - provide_deprecation_message 182 | # - public_member_api_docs # enabled on a case-by-case basis; see e.g. packages/analysis_options.yaml 183 | - recursive_getters 184 | - sized_box_for_whitespace 185 | - slash_for_doc_comments 186 | # - sort_child_properties_last # not yet tested 187 | - sort_constructors_first 188 | # - sort_pub_dependencies # prevents separating pinned transitive dependencies 189 | - sort_unnamed_constructors_first 190 | - test_types_in_equals 191 | - throw_in_finally 192 | - tighten_type_of_initializing_formals 193 | # - type_annotate_public_apis # subset of always_specify_types 194 | - type_init_formals 195 | # - unawaited_futures # too many false positives 196 | # - unnecessary_await_in_return # not yet tested 197 | - unnecessary_brace_in_string_interps 198 | - unnecessary_const 199 | # - unnecessary_final # conflicts with prefer_final_locals 200 | - unnecessary_getters_setters 201 | # - unnecessary_lambdas # has false positives: https://github.com/dart-lang/linter/issues/498 202 | - unnecessary_new 203 | - unnecessary_null_aware_assignments 204 | # - unnecessary_null_checks # not yet tested 205 | - unnecessary_null_in_if_null_operators 206 | - unnecessary_nullable_for_final_variable_declarations 207 | - unnecessary_overrides 208 | - unnecessary_parenthesis 209 | # - unnecessary_raw_strings # not yet tested 210 | - unnecessary_statements 211 | - unnecessary_string_escapes 212 | - unnecessary_string_interpolations 213 | - unnecessary_this 214 | - unrelated_type_equality_checks 215 | # - unsafe_html # not yet tested 216 | - use_full_hex_values_for_flutter_colors 217 | # - use_function_type_syntax_for_parameters # not yet tested 218 | # - use_if_null_to_convert_nulls_to_bools # not yet tested 219 | - use_is_even_rather_than_modulo 220 | - use_key_in_widget_constructors 221 | - use_late_for_private_fields_and_variables 222 | # - use_named_constants # not yet yested 223 | - use_raw_strings 224 | - use_rethrow_when_possible 225 | # - use_setters_to_change_properties # not yet tested 226 | # - use_string_buffers # has false positives: https://github.com/dart-lang/sdk/issues/34182 227 | # - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review 228 | - valid_regexps 229 | - void_checks 230 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | // 本地编译注释以下代码 28 | // start 29 | def keystorePropertiesFile = rootProject.file("key.properties") 30 | def keystoreProperties = new Properties() 31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 32 | // end 33 | android { 34 | compileSdkVersion 31 35 | 36 | compileOptions { 37 | sourceCompatibility JavaVersion.VERSION_1_8 38 | targetCompatibility JavaVersion.VERSION_1_8 39 | } 40 | 41 | kotlinOptions { 42 | jvmTarget = '1.8' 43 | } 44 | 45 | sourceSets { 46 | main.java.srcDirs += 'src/main/kotlin' 47 | } 48 | 49 | defaultConfig { 50 | applicationId "com.nightmare.termare" 51 | minSdkVersion 19 52 | targetSdkVersion 28 53 | versionCode flutterVersionCode.toInteger() 54 | versionName flutterVersionName 55 | } 56 | signingConfigs { 57 | // 本地编译注释以下代码 58 | // start 59 | release { 60 | keyAlias keystoreProperties['keyAlias'] 61 | keyPassword keystoreProperties['keyPassword'] 62 | storeFile file(keystoreProperties['storeFile']) 63 | storePassword keystoreProperties['storePassword'] 64 | } 65 | // end 66 | } 67 | buildTypes { 68 | release { 69 | signingConfig signingConfigs.release 70 | } 71 | debug { 72 | signingConfig signingConfigs.release 73 | } 74 | } 75 | } 76 | 77 | flutter { 78 | source '../..' 79 | } 80 | 81 | dependencies { 82 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 83 | } 84 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/nightmare/termare/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.nightmare.termare 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | jcenter() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.2.0' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 4 | def properties = new Properties() 5 | 6 | assert localPropertiesFile.exists() 7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 8 | 9 | def flutterSdkPath = properties.getProperty("flutter.sdk") 10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 12 | -------------------------------------------------------------------------------- /assets/fonts/DroidSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/DroidSansMono.ttf -------------------------------------------------------------------------------- /assets/fonts/MenloforPowerline.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/MenloforPowerline.ttf -------------------------------------------------------------------------------- /assets/fonts/MesloLGMforPowerline.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/MesloLGMforPowerline.ttf -------------------------------------------------------------------------------- /assets/fonts/SourceCodePro.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/SourceCodePro.ttf -------------------------------------------------------------------------------- /assets/fonts/SourceCodeProMediumforPowerline.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/SourceCodeProMediumforPowerline.otf -------------------------------------------------------------------------------- /assets/fonts/UbuntuMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/fonts/UbuntuMono.ttf -------------------------------------------------------------------------------- /assets/icons/code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/icons/code.png -------------------------------------------------------------------------------- /assets/lib/libterm.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/lib/libterm.dylib -------------------------------------------------------------------------------- /assets/ogg/InCallNotification.ogg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/assets/ogg/InCallNotification.ogg -------------------------------------------------------------------------------- /assets/text/neofetch.txt: -------------------------------------------------------------------------------- 1 | [?25l[?7l -o o- 2 | +hydNNNNdyh+ 3 | +mMMMMMMMMMMMMm+ 4 | `dMMm:NMMMMMMN:mMMd` 5 | hMMMMMMMMMMMMMMMMMMh 6 | .. yyyyyyyyyyyyyyyyyyyy .. 7 | .mMMm`MMMMMMMMMMMMMMMMMMMM`mMMm. 8 | :MMMM-MMMMMMMMMMMMMMMMMMMM-MMMM: 9 | :MMMM-MMMMMMMMMMMMMMMMMMMM-MMMM: 10 | :MMMM-MMMMMMMMMMMMMMMMMMMM-MMMM: 11 | :MMMM-MMMMMMMMMMMMMMMMMMMM-MMMM: 12 | -MMMM-MMMMMMMMMMMMMMMMMMMM-MMMM- 13 | +yy+ MMMMMMMMMMMMMMMMMMMM +yy+ 14 | mMMMMMMMMMMMMMMMMMMm 15 | `/++MMMMh++hMMMM++/` 16 | MMMMo oMMMM 17 | MMMMo oMMMM 18 | oNMm- -mMNs 19 | u0_a610@localhost 20 | ----------------- 21 | OS: Android 11 aarch64 22 | Host: Xiaomi Mi 10 23 | Kernel: 4.19.113-perf-g381838f372995 24 | Uptime: 3 days, 16 hours, 56 mins 25 | Packages: 117 (dpkg), 1 (pkg) 26 | Shell: zsh 5.8 27 | Resolution: 1080x2340x60x113680cmd 28 | CPU: Qualcomm SM8250 (8) @ 1.804GHz 29 | Memory: 5310MiB / 7612MiB 30 | 31 |          32 |          -------------------------------------------------------------------------------- /dynamic_library/libterm.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/dynamic_library/libterm.dylib -------------------------------------------------------------------------------- /dynamic_library/libterm.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/dynamic_library/libterm.so -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/ephemeral/ 22 | Flutter/app.flx 23 | Flutter/app.zip 24 | Flutter/flutter_assets/ 25 | Flutter/flutter_export_environment.sh 26 | ServiceDefinitions.json 27 | Runner/GeneratedPluginRegistrant.* 28 | 29 | # Exceptions to above rules. 30 | !default.mode1v3 31 | !default.mode2v3 32 | !default.pbxuser 33 | !default.perspectivev3 34 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | 4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 6 | 7 | project 'Runner', { 8 | 'Debug' => :debug, 9 | 'Profile' => :release, 10 | 'Release' => :release, 11 | } 12 | 13 | def flutter_root 14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 15 | unless File.exist?(generated_xcode_build_settings_path) 16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 17 | end 18 | 19 | File.foreach(generated_xcode_build_settings_path) do |line| 20 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 21 | return matches[1].strip if matches 22 | end 23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 24 | end 25 | 26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 27 | 28 | flutter_ios_podfile_setup 29 | 30 | target 'Runner' do 31 | use_frameworks! 32 | use_modular_headers! 33 | 34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 35 | end 36 | 37 | post_install do |installer| 38 | installer.pods_project.targets.each do |target| 39 | flutter_additional_ios_build_settings(target) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | termare_app 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /lib/app/modules/dashboard/views/dashboard.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/services.dart'; 3 | import 'package:get/get.dart'; 4 | import 'package:global_repository/src/utils/screen_util.dart'; 5 | import 'package:termare_app/app/modules/terminal/controllers/terminal_controller.dart'; 6 | import 'package:termare_app/app/modules/terminal/views/quark_window_check.dart'; 7 | import 'package:termare_app/app/modules/terminal/views/terminal_pages.dart'; 8 | import 'package:termare_app/app/widgets/custom_icon_button.dart'; 9 | import 'package:termare_app/themes/app_colors.dart'; 10 | 11 | class DashBoard extends StatefulWidget { 12 | const DashBoard({Key key, this.onSelect}) : super(key: key); 13 | final void Function() onSelect; 14 | 15 | @override 16 | _DashBoardState createState() => _DashBoardState(); 17 | } 18 | 19 | class _DashBoardState extends State { 20 | bool exchangeWindow = false; 21 | TerminalController controller = Get.find(); 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | if (exchangeWindow) { 26 | return Material( 27 | child: Stack( 28 | alignment: Alignment.center, 29 | children: [ 30 | QuarkWindowCheck( 31 | children: controller.getPtyTermsForCheck(), 32 | onSelect: (value) { 33 | controller.switchTo(value); 34 | widget.onSelect(); 35 | }, 36 | ), 37 | SafeArea( 38 | child: Align( 39 | alignment: Alignment.topRight, 40 | child: Padding( 41 | padding: const EdgeInsets.all(8.0), 42 | child: NiIconButton( 43 | onTap: () { 44 | exchangeWindow = false; 45 | setState(() {}); 46 | }, 47 | child: Icon(Icons.cached), 48 | ), 49 | ), 50 | ), 51 | ), 52 | ], 53 | ), 54 | ); 55 | } 56 | 57 | return AnnotatedRegion( 58 | child: Scaffold( 59 | backgroundColor: AppColors.grey.shade100, 60 | body: SafeArea( 61 | child: Padding( 62 | padding: const EdgeInsets.all(8.0), 63 | child: Column( 64 | crossAxisAlignment: CrossAxisAlignment.start, 65 | children: [ 66 | Row( 67 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 68 | children: [ 69 | Text( 70 | '本地终端', 71 | style: TextStyle( 72 | color: AppColors.fontColor, 73 | fontSize: 22.w, 74 | fontWeight: FontWeight.bold, 75 | ), 76 | ), 77 | NiIconButton( 78 | onTap: () { 79 | exchangeWindow = true; 80 | setState(() {}); 81 | }, 82 | child: Icon(Icons.cached), 83 | ), 84 | ], 85 | ), 86 | Container( 87 | width: MediaQuery.of(context).size.width, 88 | margin: EdgeInsets.symmetric(vertical: 10, horizontal: 0), 89 | padding: EdgeInsets.all(8), 90 | decoration: BoxDecoration( 91 | color: AppColors.grey.shade200, 92 | borderRadius: BorderRadius.circular(12.w), 93 | ), 94 | child: GetBuilder( 95 | builder: (controller) { 96 | final List children = []; 97 | for (int i = 0; i < controller.terms.length; i++) { 98 | children.add(TerminalItem( 99 | title: 'localhost', 100 | onTap: () { 101 | controller.switchTo(i); 102 | widget.onSelect(); 103 | }, 104 | )); 105 | } 106 | return Wrap( 107 | // crossAxisAlignment: CrossAxisAlignment.start, 108 | spacing: 12, 109 | runSpacing: 10.w, 110 | children: [ 111 | ...children, 112 | Material( 113 | color: AppColors.grey.shade300, 114 | borderRadius: BorderRadius.circular(12.w), 115 | child: Container( 116 | height: 60.w, 117 | width: 80.w, 118 | decoration: BoxDecoration( 119 | borderRadius: BorderRadius.circular(12.w), 120 | ), 121 | child: InkWell( 122 | onTap: () { 123 | controller.createPtyTerm(); 124 | }, 125 | onTapDown: (_) { 126 | Feedback.forLongPress(context); 127 | }, 128 | borderRadius: BorderRadius.circular(12.w), 129 | child: Icon(Icons.add), 130 | ), 131 | ), 132 | ), 133 | ], 134 | ); 135 | }, 136 | ), 137 | ), 138 | Text( 139 | '远程终端', 140 | style: TextStyle( 141 | color: AppColors.fontColor, 142 | fontSize: 22.w, 143 | fontWeight: FontWeight.bold, 144 | ), 145 | ), 146 | Container( 147 | width: MediaQuery.of(context).size.width, 148 | margin: EdgeInsets.symmetric(vertical: 10, horizontal: 0), 149 | padding: EdgeInsets.all(8), 150 | decoration: BoxDecoration( 151 | color: AppColors.borderColor, 152 | borderRadius: BorderRadius.circular(12.w), 153 | ), 154 | child: Wrap( 155 | // crossAxisAlignment: CrossAxisAlignment.start, 156 | spacing: 12, 157 | children: [ 158 | Material( 159 | color: AppColors.grey.shade300, 160 | borderRadius: BorderRadius.circular(12.w), 161 | child: Container( 162 | height: 60.w, 163 | width: 80.w, 164 | decoration: BoxDecoration( 165 | borderRadius: BorderRadius.circular(12.w), 166 | ), 167 | child: InkWell( 168 | onTap: () { 169 | controller.createPtyTerm(); 170 | }, 171 | onTapDown: (_) { 172 | Feedback.forLongPress(context); 173 | }, 174 | borderRadius: BorderRadius.circular(12.w), 175 | child: Icon(Icons.add), 176 | ), 177 | ), 178 | ), 179 | ], 180 | ), 181 | ), 182 | ], 183 | ), 184 | ), 185 | ), 186 | ), 187 | value: SystemUiOverlayStyle.dark, 188 | ); 189 | } 190 | } 191 | 192 | class TerminalItem extends StatelessWidget { 193 | const TerminalItem({ 194 | Key key, 195 | this.title, 196 | this.onTap, 197 | }) : super(key: key); 198 | final String title; 199 | final void Function() onTap; 200 | @override 201 | Widget build(BuildContext context) { 202 | return Material( 203 | color: Color(0xffe0e0e0), 204 | borderRadius: BorderRadius.circular(12), 205 | child: InkWell( 206 | onTap: onTap, 207 | borderRadius: BorderRadius.circular(12), 208 | child: Container( 209 | height: 60, 210 | width: 80, 211 | child: Column( 212 | mainAxisAlignment: MainAxisAlignment.center, 213 | children: [ 214 | const Icon(Icons.android), 215 | Text( 216 | title ?? '', 217 | style: TextStyle( 218 | fontSize: 12, 219 | ), 220 | ), 221 | ], 222 | ), 223 | ), 224 | ), 225 | ); 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /lib/app/modules/setting/bindings/setting_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | 3 | import '../controllers/setting_controller.dart'; 4 | 5 | class SettingBinding extends Bindings { 6 | @override 7 | void dependencies() { 8 | Get.lazyPut( 9 | () => SettingController(), 10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/app/modules/setting/controllers/setting_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:global_repository/global_repository.dart'; 6 | import 'package:termare_app/app/modules/setting/models_model.dart'; 7 | import 'package:termare_app/app/modules/terminal/controllers/terminal_controller.dart'; 8 | import 'package:termare_app/app/modules/terminal/views/terminal_pages.dart'; 9 | import 'package:termare_view/termare_view.dart'; 10 | 11 | class SettingController extends GetxController { 12 | SettingInfo settingInfo; 13 | String filePath = RuntimeEnvir.homePath + '/.termare_setting'; 14 | @override 15 | void onInit() { 16 | readLocalStorage(); 17 | super.onInit(); 18 | } 19 | 20 | void changeRepository() { 21 | // Get.dialog(Text('data')); 22 | final TextEditingController controller = TextEditingController( 23 | text: settingInfo.repository, 24 | ); 25 | showCustomDialog( 26 | context: Get.context, 27 | child: FullHeightListView( 28 | child: Column( 29 | crossAxisAlignment: CrossAxisAlignment.center, 30 | children: [ 31 | Text('更改软件源'), 32 | ClipRRect( 33 | borderRadius: BorderRadius.circular(8), 34 | child: TextField( 35 | style: const TextStyle( 36 | fontWeight: FontWeight.bold, 37 | ), 38 | controller: controller, 39 | decoration: InputDecoration( 40 | border: InputBorder.none, 41 | fillColor: const Color(0xfff0f0f0), 42 | filled: true, 43 | contentPadding: EdgeInsets.symmetric( 44 | vertical: 4, 45 | horizontal: 8, 46 | ), 47 | ), 48 | ), 49 | ), 50 | Row( 51 | mainAxisAlignment: MainAxisAlignment.end, 52 | children: [ 53 | TextButton( 54 | onPressed: () { 55 | Get.back(); 56 | }, 57 | child: Text('取消'), 58 | ), 59 | TextButton( 60 | onPressed: () { 61 | settingInfo.repository = controller.text; 62 | showToast('目前改了没用,如果你有自己编译的可以使用的源,请联系我'); 63 | saveToLocal(); 64 | Get.back(); 65 | }, 66 | child: Text('确定'), 67 | ), 68 | ], 69 | ), 70 | ], 71 | ), 72 | ), 73 | ); 74 | } 75 | 76 | void changeBufferLine() { 77 | TextEditingController controller = TextEditingController( 78 | text: settingInfo.bufferLine.toString(), 79 | ); 80 | showCustomDialog( 81 | context: Get.context, 82 | child: FullHeightListView( 83 | child: Column( 84 | crossAxisAlignment: CrossAxisAlignment.center, 85 | children: [ 86 | Text('更改缓冲行'), 87 | ClipRRect( 88 | borderRadius: BorderRadius.circular(8), 89 | child: TextField( 90 | style: const TextStyle( 91 | fontWeight: FontWeight.bold, 92 | ), 93 | controller: controller, 94 | decoration: InputDecoration( 95 | border: InputBorder.none, 96 | fillColor: const Color(0xfff0f0f0), 97 | filled: true, 98 | contentPadding: EdgeInsets.symmetric( 99 | vertical: 4, 100 | horizontal: 8, 101 | ), 102 | ), 103 | ), 104 | ), 105 | Row( 106 | mainAxisAlignment: MainAxisAlignment.end, 107 | children: [ 108 | TextButton( 109 | onPressed: () { 110 | Get.back(); 111 | }, 112 | child: Text('取消'), 113 | ), 114 | TextButton( 115 | onPressed: () { 116 | settingInfo.bufferLine = int.tryParse(controller.text); 117 | showToast('目前改了没用'); 118 | saveToLocal(); 119 | Get.back(); 120 | }, 121 | child: Text('确定'), 122 | ), 123 | ], 124 | ), 125 | ], 126 | ), 127 | ), 128 | ); 129 | } 130 | 131 | void changeCmdLine() { 132 | TextEditingController controller = TextEditingController( 133 | text: settingInfo.cmdLine.toString(), 134 | ); 135 | showCustomDialog( 136 | context: Get.context, 137 | child: FullHeightListView( 138 | child: Column( 139 | crossAxisAlignment: CrossAxisAlignment.center, 140 | children: [ 141 | Text('更改命令行'), 142 | ClipRRect( 143 | borderRadius: BorderRadius.circular(8), 144 | child: TextField( 145 | style: const TextStyle( 146 | fontWeight: FontWeight.bold, 147 | ), 148 | controller: controller, 149 | decoration: InputDecoration( 150 | border: InputBorder.none, 151 | fillColor: const Color(0xfff0f0f0), 152 | filled: true, 153 | contentPadding: EdgeInsets.symmetric( 154 | vertical: 4, 155 | horizontal: 8, 156 | ), 157 | ), 158 | ), 159 | ), 160 | Row( 161 | mainAxisAlignment: MainAxisAlignment.end, 162 | children: [ 163 | TextButton( 164 | onPressed: () { 165 | Get.back(); 166 | }, 167 | child: Text('取消'), 168 | ), 169 | TextButton( 170 | onPressed: () { 171 | settingInfo.cmdLine = controller.text; 172 | saveToLocal(); 173 | showToast('更改成功'); 174 | Get.back(); 175 | }, 176 | child: Text('确定'), 177 | ), 178 | ], 179 | ), 180 | ], 181 | ), 182 | ), 183 | ); 184 | } 185 | 186 | void changeInitCmd() { 187 | TextEditingController controller = TextEditingController( 188 | text: settingInfo.initCmd.toString(), 189 | ); 190 | showCustomDialog( 191 | context: Get.context, 192 | child: FullHeightListView( 193 | child: Column( 194 | crossAxisAlignment: CrossAxisAlignment.center, 195 | children: [ 196 | Text('更改初始命令'), 197 | SizedBox( 198 | height: 8, 199 | ), 200 | ClipRRect( 201 | borderRadius: BorderRadius.circular(8), 202 | child: TextField( 203 | style: const TextStyle( 204 | fontWeight: FontWeight.bold, 205 | ), 206 | controller: controller, 207 | decoration: InputDecoration( 208 | isDense: true, 209 | border: InputBorder.none, 210 | fillColor: const Color(0xfff0f0f0), 211 | filled: true, 212 | contentPadding: EdgeInsets.symmetric( 213 | vertical: 8, 214 | horizontal: 8, 215 | ), 216 | ), 217 | ), 218 | ), 219 | Row( 220 | mainAxisAlignment: MainAxisAlignment.end, 221 | children: [ 222 | TextButton( 223 | onPressed: () { 224 | Get.back(); 225 | }, 226 | child: Text('取消'), 227 | ), 228 | TextButton( 229 | onPressed: () { 230 | settingInfo.initCmd = controller.text; 231 | saveToLocal(); 232 | showToast('更改成功'); 233 | Get.back(); 234 | }, 235 | child: Text('确定'), 236 | ), 237 | ], 238 | ), 239 | ], 240 | ), 241 | ), 242 | ); 243 | } 244 | 245 | Future changeFontFamily(TermareController controller) async { 246 | await showCustomDialog( 247 | context: Get.context, 248 | child: FullHeightListView( 249 | child: Column( 250 | crossAxisAlignment: CrossAxisAlignment.center, 251 | children: [ 252 | Text('更改字体样式'), 253 | SizedBox( 254 | height: 8, 255 | ), 256 | Wrap( 257 | spacing: 8.0, 258 | children: [ 259 | TextButton( 260 | onPressed: () { 261 | Get.back(); 262 | settingInfo.fontFamily = 'DroidSansMono'; 263 | }, 264 | child: Text('DroidSansMono'), 265 | ), 266 | TextButton( 267 | onPressed: () { 268 | settingInfo.fontFamily = 'MenloforPowerline'; 269 | Get.back(); 270 | }, 271 | child: Text('MenloforPowerline'), 272 | ), 273 | TextButton( 274 | onPressed: () { 275 | settingInfo.fontFamily = 'SourceCodePro'; 276 | Get.back(); 277 | }, 278 | child: Text('SourceCodePro'), 279 | ), 280 | TextButton( 281 | onPressed: () { 282 | settingInfo.fontFamily = 'SourceCodeProMediumforPowerline'; 283 | Get.back(); 284 | }, 285 | child: Text('SourceCodeProMediumforPowerline'), 286 | ), 287 | TextButton( 288 | onPressed: () { 289 | settingInfo.fontFamily = 'MesloLGMforPowerline'; 290 | saveToLocal(); 291 | Get.back(); 292 | }, 293 | child: Text('MesloLGMforPowerline'), 294 | ), 295 | ], 296 | ), 297 | ], 298 | ), 299 | ), 300 | ); 301 | final TerminalController terminalController = 302 | Get.find(); 303 | for (final PtyTermEntity entity in terminalController.terms) { 304 | entity.controller.setFontfamily(settingInfo.fontFamily); 305 | } 306 | controller.setFontfamily(settingInfo.fontFamily); 307 | update(); 308 | saveToLocal(); 309 | showToast('更改成功'); 310 | } 311 | 312 | void onTextStyleChange(String value) { 313 | settingInfo.termStyle = value; 314 | saveToLocal(); 315 | update(); 316 | 317 | final TerminalController terminalController = Get.find(); 318 | for (final PtyTermEntity entity in terminalController.terms) { 319 | entity.controller.changeStyle( 320 | TermareStyle.parse(settingInfo.termStyle).copyWith( 321 | fontSize: settingInfo.fontSize.toDouble(), 322 | ), 323 | ); 324 | } 325 | 326 | showToast('更改成功'); 327 | } 328 | 329 | void readLocalStorage() { 330 | if (!Directory(RuntimeEnvir.homePath).existsSync()) { 331 | Directory(RuntimeEnvir.homePath).create(recursive: true); 332 | } 333 | print('filePath -> $filePath'); 334 | File file = File(filePath); 335 | if (file.existsSync()) { 336 | Map json = 337 | jsonDecode(file.readAsStringSync()) as Map; 338 | settingInfo = SettingInfo.fromJson(json); 339 | } else { 340 | settingInfo = SettingInfo.fromJson( 341 | { 342 | "bufferLine": 1000, 343 | "enableUtf8": true, 344 | "bellWhenEscapeA": false, 345 | "vibrationWhenEscapeA": true, 346 | "repository": "http://nightmare.fun/termare/", 347 | "cmdLine": "login", 348 | "initCmd": "", 349 | "termType": "xterm-256color", 350 | "fontSize": 11, 351 | "fontFamily": "MenloforPowerline", 352 | "termStyle": "vsCode" 353 | }, 354 | ); 355 | } 356 | } 357 | 358 | void changeInfo(SettingInfo settingInfo) { 359 | this.settingInfo = settingInfo; 360 | update(); 361 | } 362 | 363 | void saveToLocal() { 364 | final File file = File(filePath); 365 | file.writeAsString(settingInfo.toString()); 366 | } 367 | 368 | @override 369 | void onReady() { 370 | super.onReady(); 371 | } 372 | 373 | @override 374 | void onClose() {} 375 | } 376 | -------------------------------------------------------------------------------- /lib/app/modules/setting/models/models.json: -------------------------------------------------------------------------------- 1 | { 2 | "bufferLine": 1000, 3 | "enableUtf8": true, 4 | "bellWhenEscapeA": false, 5 | "vibrationWhenEscapeA": true, 6 | "repository": "http://nightmare.fun/termare/", 7 | "cmdLine": "login", 8 | "initCmd": "", 9 | "termType": "xterm-256color", 10 | "fontSize": 11, 11 | "fontFamily": "MenloforPowerline", 12 | "termStyle": "vsCode" 13 | } -------------------------------------------------------------------------------- /lib/app/modules/setting/models_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | T asT(dynamic value) { 4 | if (value is T) { 5 | return value; 6 | } 7 | 8 | return null; 9 | } 10 | 11 | class SettingInfo { 12 | SettingInfo({ 13 | this.bufferLine, 14 | this.enableUtf8, 15 | this.bellWhenEscapeA, 16 | this.vibrationWhenEscapeA, 17 | this.repository, 18 | this.cmdLine, 19 | this.initCmd, 20 | this.termType, 21 | this.fontSize, 22 | this.fontFamily, 23 | this.termStyle, 24 | }); 25 | 26 | factory SettingInfo.fromJson(Map jsonRes) => jsonRes == null 27 | ? null 28 | : SettingInfo( 29 | bufferLine: asT(jsonRes['bufferLine']), 30 | enableUtf8: asT(jsonRes['enableUtf8']), 31 | bellWhenEscapeA: asT(jsonRes['bellWhenEscapeA']), 32 | vibrationWhenEscapeA: asT(jsonRes['vibrationWhenEscapeA']), 33 | repository: asT(jsonRes['repository']), 34 | cmdLine: asT(jsonRes['cmdLine']), 35 | initCmd: asT(jsonRes['initCmd']), 36 | termType: asT(jsonRes['termType']), 37 | fontSize: asT(jsonRes['fontSize']), 38 | fontFamily: asT(jsonRes['fontFamily']), 39 | termStyle: asT(jsonRes['termStyle']), 40 | ); 41 | 42 | int bufferLine; 43 | bool enableUtf8; 44 | bool bellWhenEscapeA; 45 | bool vibrationWhenEscapeA; 46 | String repository; 47 | String cmdLine; 48 | String initCmd; 49 | String termType; 50 | int fontSize; 51 | String fontFamily; 52 | String termStyle; 53 | 54 | Map toJson() => { 55 | 'bufferLine': bufferLine, 56 | 'enableUtf8': enableUtf8, 57 | 'bellWhenEscapeA': bellWhenEscapeA, 58 | 'vibrationWhenEscapeA': vibrationWhenEscapeA, 59 | 'repository': repository, 60 | 'cmdLine': cmdLine, 61 | 'initCmd': initCmd, 62 | 'termType': termType, 63 | 'fontSize': fontSize, 64 | 'fontFamily': fontFamily, 65 | 'termStyle': termStyle, 66 | }; 67 | @override 68 | String toString() { 69 | return json.encode(this); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /lib/app/modules/setting/utils/term_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:dart_pty/dart_pty.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | import 'package:global_repository/global_repository.dart'; 7 | import 'package:path/path.dart' as p; 8 | import 'package:termare_pty/termare_pty.dart'; 9 | import 'package:termare_view/termare_view.dart'; 10 | 11 | String termLockFilePath = '${RuntimeEnvir.usrPath}/tmp/termare_pop_lock'; 12 | 13 | extension DefineFunc on PseudoTerminal { 14 | Future defineTermFunc({ 15 | @required String func, 16 | String tmpFilePath, 17 | }) async { 18 | tmpFilePath ??= 19 | RuntimeEnvir.dataPath + '${Platform.pathSeparator}defineTermFunc'; 20 | Log.d('定义函数中...--->$tmpFilePath'); 21 | 22 | final File tmpFile = File(tmpFilePath); 23 | await tmpFile.writeAsString(func); 24 | Log.d('创建临时脚本成功...->${tmpFile.path}'); 25 | 'export AUTO=TRUE\n'.split('').forEach( 26 | (String element) { 27 | write(element); 28 | }, 29 | ); 30 | Log.d('script -> source $tmpFilePath'); 31 | Log.d('rm -rf $tmpFilePath'); 32 | 'source $tmpFilePath\n'.split('').forEach( 33 | (String element) { 34 | write(element); 35 | }, 36 | ); 37 | 38 | 'rm -rf $tmpFilePath\n'.split('').forEach( 39 | (String element) { 40 | write(element); 41 | }, 42 | ); 43 | while (true) { 44 | final bool exist = await tmpFile.exists(); 45 | // 把不想被看到的代码读掉 46 | await read(); 47 | // Log.d('read()------------------->$tmp'); 48 | if (!exist) { 49 | break; 50 | } 51 | await Future.delayed(const Duration(milliseconds: 100)); 52 | } 53 | Log.d('创建临时脚本结束'); 54 | } 55 | } 56 | 57 | class TermUtils { 58 | static Future openTerm2({ 59 | @required BuildContext context, 60 | @required TermareController controller, 61 | @required String exec, 62 | @required PseudoTerminal pseudoTerminal, 63 | }) async { 64 | pseudoTerminal.write('$exec\n'); 65 | await Navigator.of(context).push( 66 | MaterialPageRoute( 67 | builder: (_) { 68 | return WillPopScope( 69 | child: AnnotatedRegion( 70 | value: SystemUiOverlayStyle.light, 71 | child: Material( 72 | color: controller.theme.backgroundColor, 73 | child: SafeArea( 74 | child: TermarePty( 75 | controller: controller, 76 | pseudoTerminal: pseudoTerminal, 77 | ), 78 | ), 79 | ), 80 | ), 81 | onWillPop: () async { 82 | final bool isLock = File(termLockFilePath).existsSync(); 83 | if (isLock) { 84 | showToast('请等待返回键释放'); 85 | } 86 | Log.d(isLock); 87 | return !isLock; 88 | }, 89 | ); 90 | }, 91 | ), 92 | ); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /lib/app/modules/setting/views/powerlevel10k_addr.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class PowerLevelAddr extends StatefulWidget { 4 | @override 5 | _PowerLevelAddrState createState() => _PowerLevelAddrState(); 6 | } 7 | 8 | class _PowerLevelAddrState extends State { 9 | @override 10 | Widget build(BuildContext context) { 11 | return Column( 12 | children: [ 13 | Text('选择地址'), 14 | Row( 15 | children: [ 16 | TextButton( 17 | onPressed: () { 18 | Navigator.pop( 19 | context, 20 | 'https://github.com/romkatv/powerlevel10k', 21 | ); 22 | }, 23 | child: Text('Github'), 24 | ), 25 | TextButton( 26 | onPressed: () { 27 | Navigator.pop( 28 | context, 29 | 'https://gitee.com/romkatv/powerlevel10k.git', 30 | ); 31 | }, 32 | child: Text('Gitee'), 33 | ), 34 | ], 35 | ), 36 | ], 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/app/modules/setting/views/zsh_select_addr.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class SelectAddr extends StatefulWidget { 4 | @override 5 | _SelectAddrState createState() => _SelectAddrState(); 6 | } 7 | 8 | class _SelectAddrState extends State { 9 | @override 10 | Widget build(BuildContext context) { 11 | return Column( 12 | children: [ 13 | Text('选择地址'), 14 | Row( 15 | children: [ 16 | TextButton( 17 | onPressed: () { 18 | Navigator.pop( 19 | context, 20 | 'https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh', 21 | ); 22 | }, 23 | child: Text('Github'), 24 | ), 25 | TextButton( 26 | onPressed: () { 27 | Navigator.pop( 28 | context, 29 | 'https://gitee.com/mirrors/oh-my-zsh/raw/master/tools/install.sh', 30 | ); 31 | }, 32 | child: Text('Gitee'), 33 | ), 34 | ], 35 | ), 36 | ], 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/bindings/terminal_binding.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | import 'package:termare_app/app/modules/setting/controllers/setting_controller.dart'; 3 | 4 | import '../controllers/terminal_controller.dart'; 5 | 6 | class TerminalBinding extends Bindings { 7 | @override 8 | void dependencies() { 9 | Get.put(SettingController()); 10 | Get.lazyPut( 11 | () => TerminalController(), 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/controllers/terminal_controller.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | import 'dart:ui'; 3 | import 'package:flutter/material.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:global_repository/global_repository.dart'; 6 | import 'package:pseudo_terminal_utils/pseudo_terminal_utils.dart'; 7 | import 'package:pty/pty.dart'; 8 | // import 'package:just_audio/just_audio.dart'; 9 | import 'package:termare_app/app/modules/setting/controllers/setting_controller.dart'; 10 | import 'package:termare_app/app/modules/setting/models_model.dart'; 11 | import 'package:termare_app/app/modules/terminal/views/download_bootstrap_page.dart'; 12 | import 'package:termare_app/app/modules/terminal/views/terminal_pages.dart'; 13 | import 'package:termare_app/app/modules/terminal/views/xterm_wrapper.dart'; 14 | import 'package:termare_app/app/widgets/termare_view_with_bar.dart'; 15 | import 'package:termare_app/config/config.dart'; 16 | import 'package:xterm/xterm.dart'; 17 | 18 | String lockFile = RuntimeEnvir.dataPath + '/cache/init_lock'; 19 | 20 | String initShell = ''' 21 | function initApp(){ 22 | cd ${RuntimeEnvir.usrPath}/ 23 | echo 准备符号链接... 24 | for line in `cat SYMLINKS.txt` 25 | do 26 | OLD_IFS="\$IFS" 27 | IFS="←" 28 | arr=(\$line) 29 | IFS="\$OLD_IFS" 30 | ln -s \${arr[0]} \${arr[3]} 31 | done 32 | rm -rf SYMLINKS.txt 33 | TMPDIR=/data/data/com.nightmare.termare/files/usr/tmp 34 | filename=bootstrap 35 | rm -rf "\$TMPDIR/\$filename*" 36 | rm -rf "\$TMPDIR/*" 37 | chmod -R 0777 ${RuntimeEnvir.binPath}/* 38 | chmod -R 0777 ${RuntimeEnvir.usrPath}/lib/* 2>/dev/null 39 | chmod -R 0777 ${RuntimeEnvir.usrPath}/libexec/* 2>/dev/null 40 | echo "\x1b[0;31m- 执行 apt update\x1b[0m" 41 | apt update 42 | echo -e "\x1b[0;32m一切处理结束\x1b[0m" 43 | rm -rf $lockFile 44 | bash 45 | } 46 | '''; 47 | 48 | class TerminalController extends GetxController { 49 | TerminalController() { 50 | envir = Map.from(Platform.environment); 51 | envir['HOME'] = RuntimeEnvir.homePath; 52 | envir['TERMUX_PREFIX'] = RuntimeEnvir.usrPath; 53 | 54 | envir['TERM'] = 'xterm-256color'; 55 | envir['PATH'] = RuntimeEnvir.path; 56 | if (File('${RuntimeEnvir.usrPath}/lib/libtermux-exec.so').existsSync()) { 57 | envir['LD_PRELOAD'] = '${RuntimeEnvir.usrPath}/lib/libtermux-exec.so'; 58 | } 59 | } 60 | List terms = []; 61 | int currentTerminal = 0; 62 | // final player = AudioPlayer(); 63 | Map envir; 64 | SettingController settingController = Get.find(); 65 | bool hasBash() { 66 | final File bashFile = File(RuntimeEnvir.binPath + '/bash'); 67 | final bool exist = bashFile.existsSync(); 68 | return exist; 69 | } 70 | 71 | Future createPtyTerm() async { 72 | // final duration = await player.setAsset( 73 | // Assets.ogg, 74 | // ); 75 | final SettingInfo settingInfo = settingController.settingInfo; 76 | final TermareController controller = TermareController( 77 | fontFamily: Config.flutterPackage + settingInfo.fontFamily, 78 | terminalTitle: 'localhost', 79 | theme: TermareStyle.parse(settingInfo.termStyle).copyWith( 80 | fontSize: settingInfo.fontSize.toDouble(), 81 | ), 82 | ); 83 | if (Platform.isAndroid) { 84 | if (!hasBash()) { 85 | // 初始化后 bash 应该存在 86 | initTerminal(controller); 87 | return; 88 | } 89 | } 90 | final Size size = window.physicalSize; 91 | final double screenWidth = size.width / window.devicePixelRatio; 92 | final double screenHeight = size.height / window.devicePixelRatio; 93 | controller.setWindowSize(Size(screenWidth, screenHeight)); 94 | Log.i('${RuntimeEnvir.binPath + '/' + 'bash'}'); 95 | envir = Map.from(Platform.environment); 96 | envir.addAll({ 97 | 'TERM': 'xterm-256color', 98 | 'PATH': '${RuntimeEnvir.binPath}:' + Platform.environment['PATH'], 99 | 'HOME': RuntimeEnvir.homePath, 100 | }); 101 | envir['TERMUX_PREFIX'] = RuntimeEnvir.usrPath; 102 | if (File('${RuntimeEnvir.usrPath}/lib/libtermux-exec.so').existsSync()) { 103 | envir['LD_PRELOAD'] = '${RuntimeEnvir.usrPath}/lib/libtermux-exec.so'; 104 | } 105 | final PseudoTerminal pseudoTerminal = PseudoTerminal.start( 106 | GetPlatform.isMacOS ? '/bin/zsh' : (RuntimeEnvir.binPath + '/' + 'bash'), 107 | ['-l'], 108 | blocking: false, 109 | workingDirectory: RuntimeEnvir.homePath, 110 | environment: envir, 111 | )..init(); 112 | Future.delayed(const Duration(milliseconds: 100), () { 113 | if (settingInfo.initCmd.isNotEmpty) { 114 | pseudoTerminal.write(settingInfo.initCmd + '\n'); 115 | } 116 | }); 117 | if (settingInfo.vibrationWhenEscapeA) { 118 | controller.onBell = () async { 119 | Feedback.forLongPress(Get.context); 120 | // player.play(); 121 | }; 122 | } 123 | terms.add( 124 | PtyTermEntity( 125 | controller, 126 | pseudoTerminal, 127 | Terminal(), 128 | ), 129 | ); 130 | update(); 131 | } 132 | 133 | List getPtyTermsForCheck() { 134 | final List widgets = []; 135 | final List terms = this.terms; 136 | for (int i = 0; i < terms.length; i++) { 137 | final PtyTermEntity entity = terms[i]; 138 | widgets.add(Hero( 139 | tag: '$i', 140 | child: XTermWrapper( 141 | pseudoTerminal: entity.pseudoTerminal, 142 | terminal: entity.terminal, 143 | ), 144 | )); 145 | } 146 | return widgets; 147 | } 148 | 149 | Future initTerminal(TermareController controller) async { 150 | // 这个 await 为了不弹太快 151 | await Future.delayed(const Duration(milliseconds: 300)); 152 | await Get.dialog(DownloadBootPage()); 153 | final PseudoTerminal pseudoTerminal = PseudoTerminal.start( 154 | '/system/bin/sh', 155 | [], 156 | blocking: false, 157 | environment: envir, 158 | )..init(); 159 | // pseudoTerminal.startPolling(); 160 | // await pseudoTerminal.defineTermFunc( 161 | // initShell, 162 | // tmpFilePath: RuntimeEnvir.filesPath + '/define', 163 | // ); 164 | pseudoTerminal.write(initShell); 165 | Log.i('初始化成功'); 166 | pseudoTerminal.write('initApp\n'); 167 | terms.add( 168 | PtyTermEntity( 169 | controller, 170 | pseudoTerminal, 171 | Terminal(), 172 | ), 173 | ); 174 | update(); 175 | } 176 | 177 | void switchTo(int value) { 178 | currentTerminal = value; 179 | update(); 180 | } 181 | 182 | Widget getCurTerm() { 183 | if (terms.isEmpty) { 184 | return const SizedBox(); 185 | } 186 | final PtyTermEntity entity = terms[currentTerminal]; 187 | return Hero( 188 | tag: '$currentTerminal', 189 | child: TermareViewWithBottomBar( 190 | pseudoTerminal: entity.pseudoTerminal, 191 | terminal: entity.terminal, 192 | termview: XTermWrapper( 193 | pseudoTerminal: entity.pseudoTerminal, 194 | terminal: entity.terminal, 195 | ), 196 | ), 197 | ); 198 | } 199 | 200 | List getPtyTerms() { 201 | final List widgets = []; 202 | final List terms = this.terms; 203 | for (int i = 0; i < terms.length; i++) { 204 | final PtyTermEntity entity = terms[i]; 205 | widgets.add( 206 | Hero( 207 | tag: '$i', 208 | child: TermareViewWithBottomBar( 209 | pseudoTerminal: entity.pseudoTerminal, 210 | termview: XTermWrapper( 211 | pseudoTerminal: entity.pseudoTerminal, 212 | terminal: entity.terminal, 213 | ), 214 | ), 215 | ), 216 | ); 217 | } 218 | return widgets; 219 | } 220 | 221 | @override 222 | void onInit() { 223 | super.onInit(); 224 | } 225 | 226 | @override 227 | void onReady() { 228 | super.onReady(); 229 | } 230 | 231 | @override 232 | void onClose() {} 233 | } 234 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/download_bootstrap_page.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:archive/archive.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:flutter/material.dart'; 6 | import 'package:global_repository/global_repository.dart'; 7 | import 'package:path/path.dart' as p; 8 | 9 | class DownloadBootPage extends StatefulWidget { 10 | @override 11 | _DownloadBootPageState createState() => _DownloadBootPageState(); 12 | } 13 | 14 | class _DownloadBootPageState extends State { 15 | @override 16 | Widget build(BuildContext context) { 17 | return Material( 18 | child: Center(child: _DownloadFile()), 19 | ); 20 | } 21 | } 22 | 23 | class _DownloadFile extends StatefulWidget { 24 | const _DownloadFile({Key key, this.callback}) : super(key: key); 25 | final void Function() callback; 26 | @override 27 | _DownloadFileState createState() => _DownloadFileState(); 28 | } 29 | 30 | class _DownloadFileState extends State<_DownloadFile> { 31 | final Dio dio = Dio(); 32 | Response response; 33 | final String filesPath = RuntimeEnvir.usrPath; 34 | List androidAdbFiles = [ 35 | 'https://nightmare-my.oss-cn-beijing.aliyuncs.com/Termare/bootstrap-aarch64.zip', 36 | ]; 37 | String cur; 38 | double fileDownratio = 0.0; 39 | String title = ''; 40 | Future downloadFile(String urlPath) async { 41 | print(urlPath); 42 | response = await dio.head(urlPath); 43 | final int fullByte = int.tryParse( 44 | response.headers.value('content-length').toString(), 45 | ); //得到服务器文件返回的字节大小 46 | // final String _human = getFileSize(_fullByte); //拿到可读的文件大小返回给用户 47 | print('fullByte======$fullByte ${p.basename(urlPath)}'); 48 | final String savePath = filesPath + '/' + p.basename(urlPath); 49 | // print(savePath); 50 | await dio.download( 51 | urlPath, 52 | savePath, 53 | onReceiveProgress: (count, total) { 54 | final double process = count / total; 55 | fileDownratio = process; 56 | setState(() {}); 57 | // ); 58 | }, 59 | ); 60 | final ProcessResult result = Process.runSync( 61 | 'chmod', 62 | [ 63 | '0777', 64 | savePath, 65 | ], 66 | environment: RuntimeEnvir.envir(), 67 | ); 68 | Log.e(result.stderr); 69 | Log.d(result.stdout); 70 | await installModule(savePath); 71 | } 72 | 73 | Future installModule(String modulePath) async { 74 | title = '解压中...'; 75 | setState(() {}); 76 | // Read the Zip file from disk. 77 | final bytes = File(modulePath).readAsBytesSync(); 78 | // Decode the Zip file 79 | final archive = ZipDecoder().decodeBytes(bytes); 80 | // Extract the contents of the Zip archive to disk. 81 | final int total = archive.length; 82 | int count = 0; 83 | // print('total -> $total count -> $count'); 84 | for (final file in archive) { 85 | final filename = file.name; 86 | final String path = '${RuntimeEnvir.usrPath}/$filename'; 87 | cur = path; 88 | print(path); 89 | if (file.isFile) { 90 | final data = file.content as List; 91 | await File(path).create(recursive: true); 92 | await File(path).writeAsBytes(data); 93 | } else { 94 | Directory(path).create( 95 | recursive: true, 96 | ); 97 | } 98 | count++; 99 | fileDownratio = count / total; 100 | print('total -> $total count -> $count'); 101 | setState(() {}); 102 | } 103 | File(modulePath).delete(); 104 | title = '配置中...'; 105 | fileDownratio = null; 106 | setState(() {}); 107 | } 108 | 109 | @override 110 | void initState() { 111 | super.initState(); 112 | execDownload(); 113 | } 114 | 115 | Future execDownload() async { 116 | List needDownloadFile; 117 | if (Platform.isAndroid) { 118 | needDownloadFile = androidAdbFiles; 119 | } 120 | for (final String urlPath in needDownloadFile) { 121 | title = '下载 ${p.basename(urlPath)} 中...'; 122 | setState(() {}); 123 | await downloadFile(urlPath); 124 | } 125 | Navigator.pop(context); 126 | } 127 | 128 | @override 129 | Widget build(BuildContext context) { 130 | return WillPopScope( 131 | child: Padding( 132 | padding: const EdgeInsets.all(8.0), 133 | child: Column( 134 | mainAxisSize: MainAxisSize.min, 135 | children: [ 136 | Text( 137 | title, 138 | style: const TextStyle( 139 | fontSize: 18, 140 | fontWeight: FontWeight.bold, 141 | ), 142 | ), 143 | const Align( 144 | alignment: Alignment.centerLeft, 145 | child: Text( 146 | '进度', 147 | style: TextStyle( 148 | fontWeight: FontWeight.bold, 149 | ), 150 | ), 151 | ), 152 | const SizedBox( 153 | height: 12, 154 | ), 155 | ClipRRect( 156 | borderRadius: const BorderRadius.all(Radius.circular(25.0)), 157 | child: LinearProgressIndicator( 158 | value: fileDownratio, 159 | ), 160 | ), 161 | SizedBox(height: 4), 162 | if (cur != null) 163 | SizedBox( 164 | child: Text( 165 | '当前处理文件 $cur', 166 | style: const TextStyle( 167 | fontWeight: FontWeight.w500, 168 | fontSize: 12, 169 | ), 170 | ), 171 | ), 172 | ], 173 | ), 174 | ), 175 | onWillPop: () async { 176 | showToast('等待下载完成后'); 177 | return false; 178 | }, 179 | ); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/quark_window_check.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | 5 | class QuarkWindowCheck extends StatefulWidget { 6 | const QuarkWindowCheck({ 7 | Key key, 8 | @required this.children, 9 | this.page, 10 | this.onSelect, 11 | }) : super(key: key); 12 | final List children; 13 | final int page; 14 | final void Function(int value) onSelect; 15 | @override 16 | _QuarkWindowCheckState createState() => _QuarkWindowCheckState(); 17 | } 18 | 19 | class _QuarkWindowCheckState extends State 20 | with TickerProviderStateMixin { 21 | AnimationController animationController; 22 | // 一个换粗你的 offset 23 | double tempOffset = 0.0; 24 | // 窗口的其起始位置 25 | int _position = 0; 26 | // 窗口范围 27 | final int _capacity = 5; 28 | 29 | List _children; 30 | double rotatedAngle = 0; 31 | List offsetList = [ 32 | 160, // 33 | 360, // 160+200 34 | 600, //360+240 35 | 880, //600+280 36 | 1200, //880+320 37 | ]; 38 | void scroll(double dy) { 39 | if (rotatedAngle < 0) { 40 | rotatedAngle += dy / 180; 41 | rotatedAngle = min(0, rotatedAngle); 42 | rotatedAngle = max(-2 * pi, rotatedAngle); 43 | return; 44 | } 45 | // Log.d(dy); 46 | if (offsetList[1] > 160) { 47 | offsetList[0] += dy * 160 / 160; 48 | offsetList[0] = max(offsetList[0], 0); 49 | if (offsetList[0] > 160) { 50 | offsetList[0] = 160; 51 | return; 52 | } 53 | } 54 | offsetList[1] += dy * 200 / 160; 55 | offsetList[1] = max(offsetList[1], 0); 56 | offsetList[2] += dy * 240 / 160; 57 | offsetList[2] = max(offsetList[2], 0); 58 | offsetList[3] += dy * 280 / 160; 59 | offsetList[3] = max(offsetList[3], 0); 60 | offsetList[4] += dy * 320 / 160; 61 | offsetList[4] = max(offsetList[4], 0); 62 | if (offsetList[1] == 0) { 63 | if (_position + 1 >= _children.length) { 64 | rotatedAngle += dy / 180; 65 | // print('rotatedAngle->$rotatedAngle'); 66 | return; 67 | } 68 | _position += 1; 69 | offsetList.removeAt(0); 70 | offsetList.add(offsetList.last + 280); 71 | } 72 | if (offsetList[0] != 0 && _position != 0) { 73 | _position -= 1; 74 | offsetList.removeLast(); 75 | offsetList.insert(0, 0); 76 | } 77 | } 78 | 79 | List generateWidget() { 80 | final List tmp = []; 81 | final int start = _position; 82 | for (int i = start; i < min(_children.length, _position + _capacity); i++) { 83 | final double offset = offsetList[i - _position]; 84 | tmp.add( 85 | Padding( 86 | padding: EdgeInsets.only(top: offset), 87 | child: Center( 88 | child: Transform( 89 | alignment: Alignment.center, 90 | transform: Matrix4.identity() 91 | ..setEntry(3, 2, 0.002) 92 | ..rotateX(rotatedAngle), 93 | child: NiCardButton( 94 | spreadRadius: 8, 95 | blurRadius: 8, 96 | shadowColor: Colors.black, 97 | borderRadius: 16, 98 | onTap: () { 99 | widget.onSelect(i); 100 | }, 101 | child: Material( 102 | color: Colors.white, 103 | child: SingleChildScrollView( 104 | physics: const NeverScrollableScrollPhysics(), 105 | child: SizedBox( 106 | width: MediaQuery.of(context).size.width - 40, 107 | height: MediaQuery.of(context).size.height * 4 / 5, 108 | child: Column( 109 | mainAxisAlignment: MainAxisAlignment.center, 110 | crossAxisAlignment: CrossAxisAlignment.center, 111 | children: [ 112 | SizedBox( 113 | height: 32.0, 114 | child: Padding( 115 | padding: EdgeInsets.symmetric( 116 | horizontal: 12, 117 | ), 118 | child: Row( 119 | mainAxisAlignment: 120 | MainAxisAlignment.spaceBetween, 121 | children: [ 122 | Text('终端[$i]'), 123 | SizedBox( 124 | width: 30, 125 | height: 30, 126 | child: InkWell( 127 | borderRadius: BorderRadius.circular(16), 128 | child: const Icon(Icons.clear), 129 | onTap: () {}, 130 | ), 131 | ), 132 | ], 133 | ), 134 | ), 135 | ), 136 | Expanded( 137 | child: AbsorbPointer( 138 | absorbing: true, 139 | child: _children[i], 140 | ), 141 | ), 142 | ], 143 | ), 144 | ), 145 | ), 146 | ), 147 | ), 148 | ), 149 | ), 150 | ), 151 | ); 152 | } 153 | return tmp; 154 | } 155 | 156 | @override 157 | void initState() { 158 | super.initState(); 159 | _children = widget.children; 160 | if (widget.page != null && widget.page > 2) { 161 | _position = max(widget.page - 2, 0); 162 | offsetList.removeLast(); 163 | offsetList.insert(0, 0); 164 | } 165 | } 166 | 167 | @override 168 | void dispose() { 169 | super.dispose(); 170 | } 171 | 172 | @override 173 | Widget build(BuildContext context) { 174 | return AnnotatedRegion( 175 | value: SystemUiOverlayStyle.dark, 176 | child: Scaffold( 177 | backgroundColor: Colors.white, 178 | body: GestureDetector( 179 | behavior: HitTestBehavior.translucent, 180 | onPanDown: (DragDownDetails details) { 181 | animationController?.stop(); 182 | tempOffset = 0; 183 | }, 184 | onVerticalDragStart: (DragStartDetails details) { 185 | tempOffset = 0; 186 | }, 187 | onVerticalDragUpdate: (DragUpdateDetails details) { 188 | scroll(details.delta.dy); 189 | 190 | // Log.d('curOffset====>$curOffset'); 191 | setState(() {}); 192 | }, 193 | onVerticalDragEnd: (DragEndDetails details) { 194 | final Tolerance tolerance = Tolerance( 195 | velocity: 1.0 / 196 | (0.050 * 197 | WidgetsBinding.instance.window 198 | .devicePixelRatio), // logical pixels per second 199 | distance: 1.0 / 200 | WidgetsBinding 201 | .instance.window.devicePixelRatio, // logical pixels 202 | ); 203 | final double start = tempOffset; 204 | final ClampingScrollSimulation clampingScrollSimulation = 205 | ClampingScrollSimulation( 206 | position: start, 207 | velocity: -details.velocity.pixelsPerSecond.dy * 2 / 3, 208 | tolerance: tolerance, 209 | ); 210 | animationController = AnimationController( 211 | vsync: this, 212 | value: 0, 213 | lowerBound: double.negativeInfinity, 214 | upperBound: double.infinity, 215 | ); 216 | animationController.reset(); 217 | animationController.addListener(() { 218 | final double offset = tempOffset - animationController.value; 219 | scroll(offset); 220 | tempOffset = animationController.value; 221 | setState(() {}); 222 | }); 223 | animationController.animateWith(clampingScrollSimulation); 224 | }, 225 | child: Stack( 226 | alignment: Alignment.topCenter, 227 | children: [ 228 | ...generateWidget(), 229 | // SafeArea( 230 | // child: Text( 231 | // '${offsetList} offset${curOffset} _position->$_position', 232 | // ), 233 | // ), 234 | ], 235 | ), 236 | ), 237 | ), 238 | ); 239 | } 240 | } 241 | 242 | class NiCardButton extends StatefulWidget { 243 | const NiCardButton({ 244 | Key key, 245 | this.child, 246 | this.onTap, 247 | this.blurRadius = 4.0, 248 | this.shadowColor = Colors.black, 249 | this.borderRadius = 8.0, 250 | this.color, 251 | this.spreadRadius = 0, 252 | this.margin = const EdgeInsets.all(8.0), 253 | }) : super(key: key); 254 | final Widget child; 255 | final Function onTap; 256 | final double blurRadius; 257 | final double borderRadius; 258 | final double spreadRadius; 259 | final Color shadowColor; 260 | final Color color; 261 | final EdgeInsetsGeometry margin; 262 | @override 263 | _NiCardButtonState createState() => _NiCardButtonState(); 264 | } 265 | 266 | class _NiCardButtonState extends State 267 | with SingleTickerProviderStateMixin { 268 | AnimationController animationController; 269 | bool isOnTap = false; 270 | @override 271 | void initState() { 272 | super.initState(); 273 | animationController = AnimationController( 274 | vsync: this, 275 | duration: const Duration(milliseconds: 100), 276 | ); 277 | animationController.addListener(() { 278 | setState(() {}); 279 | }); 280 | } 281 | 282 | @override 283 | void dispose() { 284 | animationController.dispose(); 285 | super.dispose(); 286 | } 287 | 288 | @override 289 | Widget build(BuildContext context) { 290 | return GestureDetector( 291 | behavior: HitTestBehavior.translucent, 292 | // onLongPress: () { 293 | // // print('sada'); 294 | // }, 295 | onTap: () { 296 | if (widget.onTap == null) { 297 | return; 298 | } 299 | isOnTap = false; 300 | setState(() {}); 301 | Feedback.forLongPress(context); 302 | animationController.reverse(); 303 | if (widget.onTap != null) { 304 | widget.onTap(); 305 | } 306 | }, 307 | onTapDown: (_) { 308 | if (widget.onTap == null) { 309 | return; 310 | } 311 | animationController.forward(); 312 | Feedback.forLongPress(context); 313 | isOnTap = true; 314 | setState(() {}); 315 | }, 316 | onTapCancel: () { 317 | if (widget.onTap == null) { 318 | return; 319 | } 320 | animationController.reverse(); 321 | Feedback.forLongPress(context); 322 | isOnTap = false; 323 | setState(() {}); 324 | }, 325 | child: Transform( 326 | alignment: Alignment.center, 327 | transform: Matrix4.identity() 328 | ..scale( 329 | 1.0 - animationController.value * 0.05, 330 | ), 331 | child: Container( 332 | margin: widget.margin, 333 | decoration: BoxDecoration( 334 | color: widget.color ?? Theme.of(context).cardColor, 335 | borderRadius: BorderRadius.circular(widget.borderRadius), 336 | boxShadow: [ 337 | BoxShadow( 338 | color: widget.shadowColor.withOpacity( 339 | 0.04 - animationController.value * 0.04, 340 | ), 341 | offset: const Offset(0.0, 0.0), //阴影xy轴偏移量 342 | blurRadius: widget.blurRadius, //阴影模糊程度 343 | spreadRadius: widget.spreadRadius, //阴影扩散程度 344 | ), 345 | ], 346 | ), 347 | child: ClipRRect( 348 | borderRadius: BorderRadius.circular(widget.borderRadius), 349 | child: widget.child, 350 | ), 351 | ), 352 | ), 353 | ); 354 | } 355 | } 356 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/terminal_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter/physics.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:flutter_acrylic/flutter_acrylic.dart'; 5 | import 'package:get/get.dart'; 6 | import 'package:global_repository/global_repository.dart'; 7 | import 'package:pty/pty.dart'; 8 | import 'package:termare_app/app/modules/dashboard/views/dashboard.dart'; 9 | import 'package:termare_app/app/modules/terminal/controllers/terminal_controller.dart'; 10 | import 'package:termare_app/config/config.dart'; 11 | import 'package:termare_view/termare_view.dart'; 12 | import 'package:xterm/xterm.dart' hide TerminalController; 13 | 14 | import '../../setting/views/setting_page.dart'; 15 | 16 | class PtyTermEntity { 17 | PtyTermEntity( 18 | this.controller, 19 | this.pseudoTerminal, 20 | this.terminal, 21 | ); 22 | final TermareController controller; 23 | final PseudoTerminal pseudoTerminal; 24 | final Terminal terminal; 25 | @override 26 | bool operator ==(dynamic other) { 27 | // 判断是否是非 28 | if (other is! TermareController) { 29 | return false; 30 | } 31 | if (other is TermareController) { 32 | return other.hashCode == hashCode; 33 | } 34 | return false; 35 | } 36 | 37 | @override 38 | int get hashCode => pseudoTerminal.hashCode; 39 | } 40 | 41 | class TerminalPages extends StatefulWidget { 42 | TerminalPages({ 43 | Key key, 44 | this.packageName, 45 | }) : super(key: key) { 46 | if (packageName != null) { 47 | // 改包可能是被其他项目集成的 48 | Config.packageName = packageName; 49 | Config.flutterPackage = 'packages/termare_app/'; 50 | } 51 | if (Get.arguments != null) { 52 | Config.packageName = Get.arguments.toString(); 53 | Config.flutterPackage = 'packages/termare_app/'; 54 | } 55 | } 56 | 57 | final String packageName; 58 | 59 | @override 60 | _TerminalPagesState createState() => _TerminalPagesState(); 61 | } 62 | 63 | class _TerminalPagesState extends State 64 | with TickerProviderStateMixin { 65 | TerminalController controller = Get.find(); 66 | PageController pageController = PageController(); 67 | AnimationController animationController; 68 | @override 69 | void initState() { 70 | super.initState(); 71 | if (controller.terms.isEmpty) { 72 | controller.createPtyTerm().then((value) { 73 | setState(() {}); 74 | }); 75 | } 76 | Window.makeTitlebarTransparent(); 77 | Window.enableFullSizeContentView(); 78 | Window.setEffect( 79 | effect: WindowEffect.acrylic, 80 | dark: false, 81 | ); 82 | } 83 | 84 | double offset = 0; 85 | double maxSize = 10000; 86 | double _getPixels(double page) { 87 | return page * Get.size.width; 88 | } 89 | 90 | double _getPage(double pixels) { 91 | return pixels / Get.size.width; 92 | } 93 | 94 | double _getTargetPixels( 95 | double pixels, 96 | Tolerance tolerance, 97 | double velocity, 98 | ) { 99 | double page = _getPage(pixels); 100 | Log.e('page -> $page'); 101 | if (pixels < 0) { 102 | // return 0; 103 | } 104 | if (pixels >= maxSize) { 105 | return maxSize; 106 | } 107 | if (true) { 108 | if (velocity < -tolerance.velocity) { 109 | page -= 0.5; 110 | } else if (velocity > tolerance.velocity) { 111 | page += 0.5; 112 | } 113 | return _getPixels(page.roundToDouble()); 114 | } 115 | return _getPixels(page.roundToDouble()); 116 | } 117 | 118 | final Tolerance _kDefaultTolerance = Tolerance( 119 | // TODO(ianh): Handle the case of the device pixel ratio changing. 120 | // TODO(ianh): Get this from the local MediaQuery not dart:ui's window object. 121 | velocity: 1.0 / 122 | (0.050 * 123 | WidgetsBinding 124 | .instance.window.devicePixelRatio), // logical pixels per second 125 | distance: 126 | 1.0 / WidgetsBinding.instance.window.devicePixelRatio, // logical pixels 127 | ); 128 | 129 | @override 130 | Widget build(BuildContext context) { 131 | return Material( 132 | color: Colors.transparent, 133 | child: SafeArea( 134 | child: Column( 135 | children: [ 136 | Row( 137 | children: [ 138 | SizedBox( 139 | width: 8.w, 140 | ), 141 | Container( 142 | decoration: BoxDecoration( 143 | color: Theme.of(context).primaryColor, 144 | borderRadius: BorderRadius.circular(8.w), 145 | ), 146 | padding: EdgeInsets.symmetric( 147 | horizontal: 6.w, 148 | vertical: 4.w, 149 | ), 150 | child: const Text( 151 | 'bash x', 152 | style: TextStyle( 153 | color: Colors.white, 154 | height: 1.0, 155 | ), 156 | ), 157 | ), 158 | ], 159 | ), 160 | Expanded( 161 | child: controller.getCurTerm(), 162 | ), 163 | ], 164 | ), 165 | ), 166 | ); 167 | final Map map = { 168 | 1: Builder(builder: (context) { 169 | double _offset; 170 | if (offset >= 0) { 171 | if (offset < Get.size.width / 2) { 172 | _offset = offset; 173 | } else { 174 | _offset = Get.size.width - offset; 175 | } 176 | } else if (offset < 0) { 177 | if (offset.abs() < Get.size.width / 2) { 178 | _offset = offset; 179 | } else { 180 | // Log.d('offset $offset'); 181 | _offset = -Get.size.width - offset; 182 | } 183 | } 184 | return GetBuilder(builder: (context) { 185 | return Transform( 186 | transform: Matrix4.identity()..translate(_offset), 187 | // ..scale(((Get.width - _offset.abs()) / Get.width) / 2 + 1 / 2), 188 | alignment: Alignment.center, 189 | child: AnnotatedRegion( 190 | value: SystemUiOverlayStyle.light, 191 | child: Opacity( 192 | opacity: 1.0 - 1.0 * _offset.abs() / Get.size.width, 193 | child: controller.getCurTerm(), 194 | ), 195 | ), 196 | ); 197 | }); 198 | }), 199 | }; 200 | if (offset < 0) { 201 | map[0] = Builder(builder: (context) { 202 | double _offset; 203 | if (offset.abs() < Get.size.width / 2) { 204 | _offset = -offset; 205 | } else { 206 | _offset = offset + Get.size.width; 207 | } 208 | return Opacity( 209 | opacity: 1.0, 210 | child: Transform( 211 | transform: Matrix4.identity()..translate(_offset), 212 | // ..scale(0.8), 213 | alignment: Alignment.center, 214 | child: SettingPage(), 215 | ), 216 | ); 217 | }); 218 | if (offset.abs() > Get.size.width / 2) { 219 | final Widget tmp = map[1]; 220 | map[1] = map[0]; 221 | map[0] = tmp; 222 | } 223 | } else { 224 | map[0] = Builder(builder: (context) { 225 | double _offset; 226 | if (offset < Get.size.width / 2) { 227 | _offset = -offset; 228 | } else { 229 | _offset = offset - Get.size.width; 230 | } 231 | return Transform( 232 | transform: Matrix4.identity()..translate(_offset), 233 | // ..scale(((Get.width - _offset.abs()) / Get.width) / 2 + 1 / 2), 234 | alignment: Alignment.center, 235 | child: Opacity( 236 | // opacity: 1.0 - 1.0 * (_offset.abs() / Get.size.width), 237 | opacity: 1.0, 238 | child: DashBoard( 239 | onSelect: () { 240 | animationController = AnimationController( 241 | vsync: this, 242 | value: Get.width, 243 | lowerBound: 0, 244 | upperBound: Get.width, 245 | duration: Duration(milliseconds: 300), 246 | ); 247 | animationController.reset(); 248 | animationController.addListener(() { 249 | offset = animationController.value; 250 | // Log.d(offset); 251 | setState(() {}); 252 | }); 253 | animationController.value = Get.width; 254 | animationController.reverse(); 255 | }, 256 | ), 257 | ), 258 | ); 259 | }); 260 | // Log.d('offset $offset'); 261 | // Log.d('Get.size.width / 2 ${Get.size.width / 2}'); 262 | if (offset > Get.size.width / 2) { 263 | Widget tmp = map[1]; 264 | map[1] = map[0]; 265 | map[0] = tmp; 266 | } 267 | } 268 | return AnnotatedRegion( 269 | value: SystemUiOverlayStyle.light, 270 | child: GetBuilder( 271 | init: TerminalController(), 272 | builder: (_) { 273 | return GestureDetector( 274 | behavior: HitTestBehavior.translucent, 275 | onHorizontalDragStart: (details) { 276 | animationController?.stop(); 277 | }, 278 | onHorizontalDragUpdate: (details) { 279 | offset += details.delta.dx; 280 | // Log.e(offset); 281 | setState(() {}); 282 | }, 283 | onHorizontalDragEnd: (details) { 284 | double velocity = details.velocity.pixelsPerSecond.dx; 285 | double start = offset; 286 | double target = _getTargetPixels( 287 | start, 288 | _kDefaultTolerance, 289 | velocity, 290 | ); 291 | final spring = SpringDescription.withDampingRatio( 292 | mass: 0.5, 293 | stiffness: 100.0, 294 | ratio: 1.1, 295 | ); 296 | final ScrollSpringSimulation scrollSpringSimulation = 297 | ScrollSpringSimulation( 298 | spring, 299 | start, 300 | target, 301 | velocity, 302 | tolerance: _kDefaultTolerance, 303 | ); 304 | animationController = AnimationController( 305 | vsync: this, 306 | value: 0, 307 | lowerBound: double.negativeInfinity, 308 | upperBound: double.infinity, 309 | ); 310 | animationController.reset(); 311 | animationController.addListener(() { 312 | offset = animationController.value; 313 | // Log.d(offset); 314 | setState(() {}); 315 | }); 316 | animationController.animateWith(scrollSpringSimulation); 317 | }, 318 | child: Stack( 319 | alignment: Alignment.center, 320 | children: [ 321 | map[0], 322 | map[1], 323 | ], 324 | ), 325 | ); 326 | }, 327 | ), 328 | ); 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/terminal_title.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter/material.dart'; 2 | // import 'package:termare_view/termare_view.dart'; 3 | 4 | // class TerminalTitle extends StatefulWidget { 5 | // const TerminalTitle({Key key, this.controller}) : super(key: key); 6 | // final TermareController controller; 7 | 8 | // @override 9 | // _TerminalTitleState createState() => _TerminalTitleState(); 10 | // } 11 | 12 | // class _TerminalTitleState extends State { 13 | // @override 14 | // void initState() { 15 | // super.initState(); 16 | // widget.controller?.addListener(update); 17 | // } 18 | 19 | // void update() { 20 | // if (mounted) { 21 | // setState(() {}); 22 | // } 23 | // } 24 | 25 | // @override 26 | // void dispose() { 27 | // widget.controller?.removeListener(update); 28 | // super.dispose(); 29 | // } 30 | 31 | // @override 32 | // Widget build(BuildContext context) { 33 | // return SingleChildScrollView( 34 | // scrollDirection: Axis.horizontal, 35 | // child: Center( 36 | // child: Text( 37 | // widget.controller?.terminalTitle ?? '', 38 | // style: const TextStyle( 39 | // height: 1.0, 40 | // fontWeight: FontWeight.bold, 41 | // ), 42 | // ), 43 | // ), 44 | // ); 45 | // } 46 | // } 47 | -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/web_view.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:webview_flutter/webview_flutter.dart'; 5 | 6 | class WebViewExample extends StatefulWidget { 7 | @override 8 | WebViewExampleState createState() => WebViewExampleState(); 9 | } 10 | 11 | class WebViewExampleState extends State { 12 | @override 13 | void initState() { 14 | super.initState(); 15 | // Enable hybrid composition. 16 | if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView(); 17 | } 18 | 19 | @override 20 | Widget build(BuildContext context) { 21 | return const WebView( 22 | initialUrl: 'http://127.0.0.1:8080', 23 | ); 24 | } 25 | } -------------------------------------------------------------------------------- /lib/app/modules/terminal/views/xterm_wrapper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:get/utils.dart'; 5 | import 'package:pty/pty.dart'; 6 | import 'package:xterm/xterm.dart'; 7 | 8 | class XTermWrapper extends StatefulWidget { 9 | const XTermWrapper({ 10 | Key key, 11 | this.terminal, 12 | this.pseudoTerminal, 13 | }) : super(key: key); 14 | final Terminal terminal; 15 | final PseudoTerminal pseudoTerminal; 16 | 17 | @override 18 | State createState() => _XTermWrapperState(); 19 | } 20 | 21 | class _XTermWrapperState extends State { 22 | StreamSubscription streamSubscription; 23 | 24 | @override 25 | void initState() { 26 | super.initState(); 27 | // print('$this init'); 28 | // print('\x1b[31m监听的id 为${pseudoTerminal.pseudoTerminalId}'); 29 | // 延时有用,是termare_app引起的。 30 | // PageView.builder会在短时间init与dispose这个widget 31 | // if (!mounted) { 32 | // return; 33 | // } 34 | widget.terminal.onOutput = (data) { 35 | widget.pseudoTerminal.write(data); 36 | }; 37 | 38 | widget.terminal.onResize = (width, height, pixelWidth, pixelHeight) { 39 | widget.pseudoTerminal.resize(width, height); 40 | }; 41 | streamSubscription ??= widget.pseudoTerminal.out.listen( 42 | (String data) { 43 | widget.terminal.write(data); 44 | }, 45 | ); 46 | } 47 | 48 | @override 49 | Widget build(BuildContext context) { 50 | return TerminalView( 51 | widget.terminal, 52 | backgroundOpacity: 0, 53 | keyboardType: TextInputType.text, 54 | theme: GetPlatform.isAndroid ? android : theme, 55 | ); 56 | } 57 | } 58 | 59 | TerminalTheme android = const TerminalTheme( 60 | cursor: Color(0XAAAEAFAD), 61 | selection: Color(0XFFFFFF40), 62 | foreground: Colors.white, 63 | background: Color(0XFF000000), 64 | black: Color(0XFF000000), 65 | red: Color(0XFFCD3131), 66 | green: Color(0XFF0DBC79), 67 | yellow: Color(0XFFE5E510), 68 | blue: Color(0XFF2472C8), 69 | magenta: Color(0XFFBC3FBC), 70 | cyan: Color(0XFF11A8CD), 71 | white: Color(0XFFE5E5E5), 72 | brightBlack: Color(0XFF666666), 73 | brightRed: Color(0XFFF14C4C), 74 | brightGreen: Color(0XFF23D18B), 75 | brightYellow: Color(0XFFF5F543), 76 | brightBlue: Color(0XFF3B8EEA), 77 | brightMagenta: Color(0XFFD670D6), 78 | brightCyan: Color(0XFF29B8DB), 79 | brightWhite: Color(0XFFFFFFFF), 80 | searchHitBackground: Color(0XFFFFFF2B), 81 | searchHitBackgroundCurrent: Color(0XFF31FF26), 82 | searchHitForeground: Color(0XFF000000), 83 | ); 84 | 85 | TerminalTheme theme = const TerminalTheme( 86 | cursor: Color(0XAAAEAFAD), 87 | selection: Color(0XFFFFFF40), 88 | foreground: Color(0XFF000000), 89 | background: Color(0XFF000000), 90 | black: Color(0XFF000000), 91 | red: Color(0XFFCD3131), 92 | green: Color(0XFF0DBC79), 93 | yellow: Color(0XFFE5E510), 94 | blue: Color(0XFF2472C8), 95 | magenta: Color(0XFFBC3FBC), 96 | cyan: Color(0XFF11A8CD), 97 | white: Color(0XFFE5E5E5), 98 | brightBlack: Color(0XFF666666), 99 | brightRed: Color(0XFFF14C4C), 100 | brightGreen: Color(0XFF23D18B), 101 | brightYellow: Color(0XFFF5F543), 102 | brightBlue: Color(0XFF3B8EEA), 103 | brightMagenta: Color(0XFFD670D6), 104 | brightCyan: Color(0XFF29B8DB), 105 | brightWhite: Color(0XFFFFFFFF), 106 | searchHitBackground: Color(0XFFFFFF2B), 107 | searchHitBackgroundCurrent: Color(0XFF31FF26), 108 | searchHitForeground: Color(0XFF000000), 109 | ); 110 | -------------------------------------------------------------------------------- /lib/app/routes/app_pages.dart: -------------------------------------------------------------------------------- 1 | import 'package:get/get.dart'; 2 | 3 | import 'package:termare_app/app/modules/setting/bindings/setting_binding.dart'; 4 | import 'package:termare_app/app/modules/setting/views/setting_page.dart'; 5 | import 'package:termare_app/app/modules/terminal/bindings/terminal_binding.dart'; 6 | import 'package:termare_app/app/modules/terminal/views/terminal_pages.dart'; 7 | 8 | part 'app_routes.dart'; 9 | 10 | class AppPages { 11 | AppPages._(); 12 | 13 | static const INITIAL = Routes.HOME; 14 | 15 | static final routes = [ 16 | GetPage( 17 | name: Routes.HOME, 18 | page: () => TerminalPages(), 19 | binding: TerminalBinding(), 20 | ), 21 | GetPage( 22 | name: Routes.SETTING, 23 | page: () => SettingPage(), 24 | binding: SettingBinding(), 25 | ), 26 | ]; 27 | } 28 | -------------------------------------------------------------------------------- /lib/app/routes/app_routes.dart: -------------------------------------------------------------------------------- 1 | part of 'app_pages.dart'; 2 | // DO NOT EDIT. This is code generated via package:get_cli/get_cli.dart 3 | 4 | abstract class Routes { 5 | static const String prefix = '/termareApp'; 6 | static const HOME = '$prefix/home'; 7 | static const SETTING = '$prefix/setting'; 8 | } 9 | -------------------------------------------------------------------------------- /lib/app/widgets/custom_icon_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:global_repository/global_repository.dart'; 3 | 4 | class NiIconButton extends StatelessWidget { 5 | const NiIconButton({Key key, this.child, this.onTap}) : super(key: key); 6 | final Widget child; 7 | final GestureTapCallback onTap; 8 | @override 9 | Widget build(BuildContext context) { 10 | return Container( 11 | width: 36, 12 | height: 36, 13 | child: InkWell( 14 | canRequestFocus: false, 15 | borderRadius: BorderRadius.circular(24), 16 | onTap: onTap, 17 | child: child, 18 | ), 19 | ); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/app/widgets/mac_safearea.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_acrylic/flutter_acrylic.dart'; 3 | import 'package:get/utils.dart'; 4 | 5 | double titlebarHeight = 0; 6 | 7 | class MacSafeArea extends StatefulWidget { 8 | const MacSafeArea({ 9 | Key key, 10 | this.child, 11 | }) : super(key: key); 12 | final Widget child; 13 | 14 | @override 15 | State createState() => _MacSafeAreaState(); 16 | } 17 | 18 | class _MacSafeAreaState extends State { 19 | Future calculateTitlebarHeight() async { 20 | if (!GetPlatform.isMacOS) { 21 | return; 22 | } 23 | titlebarHeight = await Window.getTitlebarHeight(); 24 | setState(() {}); 25 | } 26 | 27 | @override 28 | void initState() { 29 | super.initState(); 30 | calculateTitlebarHeight(); 31 | } 32 | 33 | @override 34 | Widget build(BuildContext context) { 35 | return Padding( 36 | padding: EdgeInsets.only(top: titlebarHeight), 37 | child: widget.child, 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/app/widgets/pop_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class PopButton extends StatelessWidget { 4 | /// 路由栈使用的时候会有些问题 5 | const PopButton({Key key, this.navigatorContext}) : super(key: key); 6 | final BuildContext navigatorContext; 7 | 8 | @override 9 | Widget build(BuildContext context) { 10 | return Align( 11 | alignment: Alignment.center, 12 | child: Container( 13 | decoration: BoxDecoration(borderRadius: BorderRadius.circular(25)), 14 | height: 36, 15 | width: 36, 16 | child: InkWell( 17 | borderRadius: BorderRadius.circular(25), 18 | child: const Icon( 19 | Icons.arrow_back, 20 | color: Colors.black, 21 | ), 22 | onTap: () { 23 | Navigator.pop(context ?? navigatorContext); 24 | }, 25 | ), 26 | ), 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/app/widgets/term_bottom_bar.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:global_repository/src/utils/screen_util.dart'; 5 | import 'package:pty/pty.dart'; 6 | import 'package:xterm/xterm.dart'; 7 | 8 | class TerminalFoot extends StatefulWidget { 9 | const TerminalFoot({Key key, this.pseudoTerminal, this.terminal}) 10 | : super(key: key); 11 | final PseudoTerminal pseudoTerminal; 12 | final Terminal terminal; 13 | 14 | @override 15 | _TerminalFootState createState() => _TerminalFootState(); 16 | } 17 | 18 | class _TerminalFootState extends State 19 | with SingleTickerProviderStateMixin { 20 | Color defaultDragColor = Colors.white.withOpacity(0.4); 21 | Animation height; 22 | AnimationController controller; 23 | Color dragColor; 24 | @override 25 | void initState() { 26 | super.initState(); 27 | dragColor = defaultDragColor; 28 | controller = AnimationController( 29 | vsync: this, 30 | duration: Duration(milliseconds: 100), 31 | ); 32 | height = Tween(begin: 18.0, end: 82).animate(CurvedAnimation( 33 | curve: Curves.easeIn, 34 | parent: controller, 35 | )); 36 | height.addListener(() { 37 | setState(() {}); 38 | }); 39 | } 40 | 41 | @override 42 | void dispose() { 43 | super.dispose(); 44 | } 45 | 46 | @override 47 | Widget build(BuildContext context) { 48 | return SizedBox( 49 | width: 414.w, 50 | height: height.value, 51 | child: SingleChildScrollView( 52 | physics: const NeverScrollableScrollPhysics(), 53 | child: Column( 54 | children: [ 55 | GestureDetector( 56 | behavior: HitTestBehavior.translucent, 57 | onPanDown: (_) { 58 | dragColor = Colors.white.withOpacity(0.8); 59 | setState(() {}); 60 | }, 61 | onPanCancel: () { 62 | dragColor = defaultDragColor; 63 | setState(() {}); 64 | }, 65 | onPanEnd: (_) { 66 | dragColor = defaultDragColor; 67 | setState(() {}); 68 | }, 69 | onTap: () { 70 | if (controller.isCompleted) { 71 | controller.reverse(); 72 | } else { 73 | controller.forward(); 74 | } 75 | }, 76 | child: SizedBox( 77 | height: 16, 78 | child: Center( 79 | child: Container( 80 | width: 100, 81 | height: 4, 82 | decoration: BoxDecoration( 83 | color: dragColor, 84 | borderRadius: BorderRadius.circular(3), 85 | ), 86 | ), 87 | ), 88 | ), 89 | ), 90 | SizedBox( 91 | height: 2, 92 | ), 93 | Row( 94 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 95 | children: [ 96 | Expanded( 97 | child: BottomItem( 98 | pseudoTerminal: widget.pseudoTerminal, 99 | title: 'ESC', 100 | onTap: () { 101 | // widget.pseudoTerminal.input?.call( 102 | // utf8.decode([0x1b]), 103 | // ); 104 | }, 105 | ), 106 | ), 107 | Expanded( 108 | child: BottomItem( 109 | pseudoTerminal: widget.pseudoTerminal, 110 | title: 'TAB', 111 | onTap: () { 112 | // widget.pseudoTerminal.input?.call( 113 | // utf8.decode([9]), 114 | // ); 115 | }, 116 | ), 117 | ), 118 | Expanded( 119 | child: BottomItem( 120 | pseudoTerminal: widget.pseudoTerminal, 121 | title: 'CTRL', 122 | enable: false, 123 | onTap: () { 124 | // widget.pseudoTerminal.enbaleOrDisableCtrl(); 125 | // setState(() {}); 126 | }, 127 | ), 128 | ), 129 | Expanded( 130 | child: BottomItem( 131 | pseudoTerminal: widget.pseudoTerminal, 132 | title: 'ALT', 133 | ), 134 | ), 135 | Expanded( 136 | child: BottomItem( 137 | pseudoTerminal: widget.pseudoTerminal, 138 | title: '-', 139 | onTap: () { 140 | // widget.pseudoTerminal.input?.call( 141 | // utf8.decode([110 - 96]), 142 | // ); 143 | }, 144 | ), 145 | ), 146 | Expanded( 147 | child: BottomItem( 148 | pseudoTerminal: widget.pseudoTerminal, 149 | title: '↑', 150 | onTap: () { 151 | // widget.pseudoTerminal.input?.call( 152 | // utf8.decode([112 - 96]), 153 | // ); 154 | }, 155 | ), 156 | ), 157 | Expanded( 158 | child: BottomItem( 159 | pseudoTerminal: widget.pseudoTerminal, 160 | title: '↲', 161 | onTap: () { 162 | widget.terminal.keyInput(TerminalKey.enter); 163 | // widget.pseudoTerminal.input?.call( 164 | // utf8.decode([110 - 96]), 165 | // ); 166 | }, 167 | ), 168 | ), 169 | ], 170 | ), 171 | Row( 172 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 173 | children: [ 174 | Expanded( 175 | child: BottomItem( 176 | pseudoTerminal: widget.pseudoTerminal, 177 | title: 'INS', 178 | onTap: () { 179 | // widget.pseudoTerminal.input?.call( 180 | // utf8.decode([0x1b]), 181 | // ); 182 | }, 183 | ), 184 | ), 185 | Expanded( 186 | child: BottomItem( 187 | pseudoTerminal: widget.pseudoTerminal, 188 | title: 'END', 189 | onTap: () { 190 | // widget.pseudoTerminal.input?.call( 191 | // utf8.decode([9]), 192 | // ); 193 | }, 194 | ), 195 | ), 196 | Expanded( 197 | child: BottomItem( 198 | pseudoTerminal: widget.pseudoTerminal, 199 | title: 'SHIFT', 200 | onTap: () { 201 | // widget.pseudoTerminal.enbaleOrDisableCtrl(); 202 | // setState(() {}); 203 | }, 204 | ), 205 | ), 206 | Expanded( 207 | child: BottomItem( 208 | pseudoTerminal: widget.pseudoTerminal, 209 | title: ':', 210 | ), 211 | ), 212 | Expanded( 213 | child: BottomItem( 214 | pseudoTerminal: widget.pseudoTerminal, 215 | title: '←', 216 | onTap: () { 217 | // widget.pseudoTerminal.input?.call( 218 | // utf8.decode([112 - 96]), 219 | // ); 220 | }, 221 | ), 222 | ), 223 | Expanded( 224 | child: BottomItem( 225 | pseudoTerminal: widget.pseudoTerminal, 226 | title: '↓', 227 | onTap: () { 228 | // widget.pseudoTerminal.input?.call( 229 | // utf8.decode([110 - 96]), 230 | // ); 231 | }, 232 | ), 233 | ), 234 | Expanded( 235 | child: BottomItem( 236 | pseudoTerminal: widget.pseudoTerminal, 237 | title: '→', 238 | onTap: () { 239 | // widget.pseudoTerminal.input?.call( 240 | // utf8.decode([110 - 96]), 241 | // ); 242 | }, 243 | ), 244 | ), 245 | ], 246 | ), 247 | ], 248 | ), 249 | ), 250 | ); 251 | } 252 | } 253 | 254 | class BottomItem extends StatefulWidget { 255 | const BottomItem({ 256 | Key key, 257 | this.pseudoTerminal, 258 | this.title, 259 | this.onTap, 260 | this.enable = false, 261 | }) : super(key: key); 262 | final PseudoTerminal pseudoTerminal; 263 | final String title; 264 | final void Function() onTap; 265 | final bool enable; 266 | 267 | @override 268 | _BottomItemState createState() => _BottomItemState(); 269 | } 270 | 271 | class _BottomItemState extends State { 272 | Color backgroundColor = Colors.transparent; 273 | 274 | @override 275 | void initState() { 276 | super.initState(); 277 | } 278 | 279 | @override 280 | void dispose() { 281 | super.dispose(); 282 | } 283 | 284 | @override 285 | Widget build(BuildContext context) { 286 | return GestureDetector( 287 | behavior: HitTestBehavior.opaque, 288 | // onTap: widget.onTap, 289 | onPanDown: (_) { 290 | widget.onTap?.call(); 291 | backgroundColor = Colors.white.withOpacity(0.2); 292 | setState(() {}); 293 | Feedback.forLongPress(context); 294 | }, 295 | onPanEnd: (_) { 296 | backgroundColor = Colors.transparent; 297 | setState(() {}); 298 | Feedback.forLongPress(context); 299 | }, 300 | onPanCancel: () { 301 | backgroundColor = Colors.transparent; 302 | setState(() {}); 303 | Feedback.forLongPress(context); 304 | }, 305 | child: Container( 306 | decoration: BoxDecoration( 307 | color: 308 | widget.enable ? Colors.white.withOpacity(0.4) : backgroundColor, 309 | ), 310 | height: 30, 311 | child: Center( 312 | child: Text( 313 | widget.title, 314 | style: TextStyle( 315 | color: Colors.white, 316 | fontWeight: FontWeight.w500, 317 | ), 318 | ), 319 | ), 320 | ), 321 | ); 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /lib/app/widgets/termare_view_with_bar.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/material.dart'; 3 | import 'package:flutter/services.dart'; 4 | import 'package:global_repository/global_repository.dart'; 5 | import 'package:pty/pty.dart'; 6 | import 'package:xterm/xterm.dart'; 7 | import 'term_bottom_bar.dart'; 8 | 9 | class TermareViewWithBottomBar extends StatefulWidget { 10 | const TermareViewWithBottomBar({ 11 | Key key, 12 | this.termview, 13 | this.pseudoTerminal, 14 | this.terminal, 15 | }) : super(key: key); 16 | final Widget termview; 17 | final PseudoTerminal pseudoTerminal; 18 | final Terminal terminal; 19 | @override 20 | _TermareViewWithBottomBarState createState() => 21 | _TermareViewWithBottomBarState(); 22 | } 23 | 24 | class _TermareViewWithBottomBarState extends State { 25 | @override 26 | void dispose() { 27 | super.dispose(); 28 | } 29 | 30 | SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle.light; 31 | @override 32 | Widget build(BuildContext context) { 33 | return AnnotatedRegion( 34 | value: systemUiOverlayStyle, 35 | child: Scaffold( 36 | resizeToAvoidBottomInset: true, 37 | backgroundColor: Colors.transparent, 38 | body: SafeArea( 39 | child: Stack( 40 | children: [ 41 | Column( 42 | children: [ 43 | Expanded( 44 | child: widget.termview, 45 | ), 46 | TerminalFoot( 47 | pseudoTerminal: widget.pseudoTerminal, 48 | terminal: widget.terminal, 49 | ), 50 | ], 51 | ), 52 | // if (PlatformUtil.isDesktop()) 53 | // Align( 54 | // alignment: Alignment.topRight, 55 | // child: SizedBox( 56 | // height: 32.0, 57 | // child: IconButton( 58 | // onPressed: () { 59 | // Navigator.pop(context); 60 | // }, 61 | // icon: const Icon( 62 | // Icons.clear, 63 | // color: Colors.white, 64 | // ), 65 | // ), 66 | // ), 67 | // ), 68 | ], 69 | ), 70 | ), 71 | ), 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/app/widgets/terminal_drawer.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter/cupertino.dart'; 2 | // import 'package:flutter/material.dart'; 3 | // import 'package:termare_app/modules/code/code_list.dart'; 4 | // import 'package:termare_app/modules/setting/setting_page.dart'; 5 | // import 'package:termare_view/termare_view.dart'; 6 | 7 | // class TerminalDrawer extends StatefulWidget { 8 | // const TerminalDrawer({Key key, this.controller}) : super(key: key); 9 | // final TermareController controller; 10 | 11 | // @override 12 | // _TerminalDrawerState createState() => _TerminalDrawerState(); 13 | // } 14 | 15 | // class _TerminalDrawerState extends State { 16 | // final children = { 17 | // 0: const Text( 18 | // '视图', 19 | // style: TextStyle(color: Colors.white), 20 | // ), 21 | // 1: const Text( 22 | // '代码片段', 23 | // style: TextStyle(color: Colors.white), 24 | // ), 25 | // }; 26 | 27 | // int currentSegment = 0; 28 | 29 | // void onValueChanged(int newValue) { 30 | // setState(() { 31 | // currentSegment = newValue; 32 | // }); 33 | // } 34 | 35 | // @override 36 | // Widget build(BuildContext context) { 37 | // return SizedBox( 38 | // width: MediaQuery.of(context).size.width, 39 | // height: MediaQuery.of(context).size.height, 40 | // child: Padding( 41 | // padding: const EdgeInsets.fromLTRB(32, 64, 32, 32), 42 | // child: Material( 43 | // textStyle: const TextStyle( 44 | // color: Colors.white, 45 | // ), 46 | // borderRadius: BorderRadius.circular(8), 47 | // color: Colors.black.withOpacity(0.2), 48 | // child: SafeArea( 49 | // child: Column( 50 | // children: [ 51 | // SizedBox( 52 | // width: 500, 53 | // child: Padding( 54 | // padding: const EdgeInsets.all(16), 55 | // child: CupertinoSlidingSegmentedControl( 56 | // backgroundColor: Colors.white.withOpacity(0.2), 57 | // children: children, 58 | // onValueChanged: onValueChanged, 59 | // groupValue: currentSegment, 60 | // thumbColor: Colors.white.withOpacity(0.2), 61 | // ), 62 | // ), 63 | // ), 64 | // Expanded( 65 | // child: [ 66 | // Column( 67 | // children: [ 68 | // const Text('字体大小'), 69 | // Row( 70 | // mainAxisAlignment: MainAxisAlignment.spaceBetween, 71 | // children: [ 72 | // IconButton( 73 | // icon: const Icon( 74 | // Icons.remove, 75 | // color: Colors.white, 76 | // ), 77 | // onPressed: () { 78 | // widget.controller.setFontSize( 79 | // widget.controller.theme.fontSize - 1, 80 | // ); 81 | // setState(() {}); 82 | // }, 83 | // ), 84 | // Text(widget.controller.theme.fontSize.toString()), 85 | // IconButton( 86 | // icon: const Icon( 87 | // Icons.add, 88 | // color: Colors.white, 89 | // ), 90 | // onPressed: () { 91 | // widget.controller.setFontSize( 92 | // widget.controller.theme.fontSize + 1, 93 | // ); 94 | // setState(() {}); 95 | // }, 96 | // ), 97 | // ], 98 | // ), 99 | // Row( 100 | // mainAxisAlignment: MainAxisAlignment.spaceAround, 101 | // children: [ 102 | // const Text('显示网格'), 103 | // Checkbox( 104 | // checkColor: Colors.black, 105 | // // c: MaterialStateProperty.resolveWith((_) { 106 | // // return Colors.white; 107 | // // }), 108 | // value: widget.controller.showBackgroundLine, 109 | // onChanged: (value) { 110 | // widget.controller.showBackgroundLine = value; 111 | // widget.controller.dirty = true; 112 | // setState(() {}); 113 | // widget.controller.notifyListeners(); 114 | // }, 115 | // ), 116 | // ], 117 | // ), 118 | // Column( 119 | // children: [ 120 | // Container( 121 | // color: TermareStyles.termux.backgroundColor, 122 | // child: Row( 123 | // mainAxisAlignment: 124 | // MainAxisAlignment.spaceBetween, 125 | // children: [ 126 | // Text( 127 | // 'termux', 128 | // style: TextStyle( 129 | // color: TermareStyles.termux.defaultColor, 130 | // ), 131 | // ), 132 | // TermColorList( 133 | // style: TermareStyles.termux, 134 | // ), 135 | // Radio( 136 | // value: TermareStyles.termux, 137 | // groupValue: termareStyle, 138 | // onChanged: (v) { 139 | // termareStyle = v; 140 | // // systemUiOverlayStyle = 141 | // // SystemUiOverlayStyle.light; 142 | // setState(() {}); 143 | // widget.controller.theme = 144 | // termareStyle.copyWith( 145 | // fontSize: 146 | // widget.controller.theme.fontSize, 147 | // ); 148 | // widget.controller.dirty = true; 149 | // widget.controller.notifyListeners(); 150 | // }, 151 | // ), 152 | // ], 153 | // ), 154 | // ), 155 | // Container( 156 | // color: TermareStyles.manjaro.backgroundColor, 157 | // child: Row( 158 | // mainAxisAlignment: 159 | // MainAxisAlignment.spaceBetween, 160 | // children: [ 161 | // Text( 162 | // 'manjaro', 163 | // style: TextStyle( 164 | // color: TermareStyles.manjaro.defaultColor, 165 | // ), 166 | // ), 167 | // TermColorList( 168 | // style: TermareStyles.manjaro, 169 | // ), 170 | // Radio( 171 | // value: TermareStyles.manjaro, 172 | // groupValue: termareStyle, 173 | // onChanged: (v) { 174 | // termareStyle = v; 175 | // // systemUiOverlayStyle = 176 | // // SystemUiOverlayStyle.light; 177 | // setState(() {}); 178 | // widget.controller.theme = 179 | // termareStyle.copyWith( 180 | // fontSize: 181 | // widget.controller.theme.fontSize, 182 | // ); 183 | // widget.controller.dirty = true; 184 | // widget.controller.notifyListeners(); 185 | // }, 186 | // ), 187 | // ], 188 | // ), 189 | // ), 190 | // Container( 191 | // color: TermareStyles.macos.backgroundColor, 192 | // child: Row( 193 | // mainAxisAlignment: 194 | // MainAxisAlignment.spaceBetween, 195 | // children: [ 196 | // Text( 197 | // 'macos', 198 | // style: TextStyle( 199 | // color: TermareStyles.macos.defaultColor, 200 | // ), 201 | // ), 202 | // TermColorList( 203 | // style: TermareStyles.macos, 204 | // ), 205 | // Radio( 206 | // value: TermareStyles.macos, 207 | // groupValue: termareStyle, 208 | // onChanged: (v) { 209 | // termareStyle = v; 210 | // // systemUiOverlayStyle = 211 | // // SystemUiOverlayStyle.dark; 212 | // setState(() {}); 213 | // widget.controller.theme = 214 | // termareStyle.copyWith( 215 | // fontSize: 216 | // widget.controller.theme.fontSize, 217 | // ); 218 | // widget.controller.dirty = true; 219 | // widget.controller.notifyListeners(); 220 | // }, 221 | // ), 222 | // ], 223 | // ), 224 | // ), 225 | // ], 226 | // ), 227 | // ], 228 | // ), 229 | // LayoutBuilder( 230 | // builder: (c, cc) { 231 | // print(cc.maxHeight); 232 | // return Scaffold( 233 | // backgroundColor: Colors.transparent, 234 | // body: Theme( 235 | // data: ThemeData( 236 | // textTheme: const TextTheme( 237 | // subtitle1: TextStyle( 238 | // fontSize: 16.0, 239 | // fontWeight: FontWeight.bold, 240 | // color: Colors.white, 241 | // ), 242 | // bodyText2: TextStyle( 243 | // fontSize: 14.0, 244 | // color: Colors.white, 245 | // ), 246 | // ), 247 | // ), 248 | // child: CodeListPage( 249 | // controller: widget.controller, 250 | // ), 251 | // ), 252 | // ); 253 | // }, 254 | // ), 255 | // ][currentSegment], 256 | // ) 257 | // ], 258 | // ), 259 | // ), 260 | // ), 261 | // ), 262 | // ); 263 | // } 264 | // } 265 | -------------------------------------------------------------------------------- /lib/config/assets.dart: -------------------------------------------------------------------------------- 1 | import 'config.dart'; 2 | 3 | class Assets { 4 | Assets._(); 5 | static String neofetchContent = 6 | Config.flutterPackage + 'assets/text/neofetch.txt'; 7 | static String ogg = 8 | Config.flutterPackage + 'assets/ogg/InCallNotification.ogg'; 9 | } 10 | -------------------------------------------------------------------------------- /lib/config/config.dart: -------------------------------------------------------------------------------- 1 | import 'package:global_repository/global_repository.dart'; 2 | 3 | class Config { 4 | Config._(); 5 | static String bashPath = '${RuntimeEnvir.binPath}/bash'; 6 | static String packageName = 'com.nightmare.termare'; 7 | // flutter package名,因为这个会影响assets的路径 8 | static String flutterPackage = ''; 9 | } 10 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | import 'dart:io'; 3 | 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter/services.dart'; 6 | import 'package:flutter_acrylic/flutter_acrylic.dart'; 7 | 8 | import 'package:get/get.dart'; 9 | import 'package:global_repository/global_repository.dart'; 10 | 11 | import 'app/routes/app_pages.dart'; 12 | 13 | Future main() async { 14 | RuntimeEnvir.initEnvirWithPackageName('com.nightmare.termare'); 15 | WidgetsFlutterBinding.ensureInitialized(); 16 | if (GetPlatform.isDesktop) { 17 | await Window.initialize(); 18 | } 19 | runApp( 20 | ToastApp( 21 | child: GetMaterialApp( 22 | // showPerformanceOverlay: true, 23 | title: 'Termare开源版', 24 | initialRoute: AppPages.INITIAL, 25 | getPages: AppPages.routes, 26 | defaultTransition: Transition.fade, 27 | ), 28 | ), 29 | ); 30 | SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( 31 | statusBarColor: Colors.transparent, 32 | systemNavigationBarColor: Colors.transparent, 33 | systemNavigationBarDividerColor: Colors.transparent, 34 | )); 35 | } 36 | -------------------------------------------------------------------------------- /lib/termare_app.dart: -------------------------------------------------------------------------------- 1 | export 'app/routes/app_pages.dart'; 2 | -------------------------------------------------------------------------------- /lib/themes/app_colors.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | const MaterialColor _grey = MaterialColor( 6 | _greyPrimaryValue, 7 | { 8 | // 对应UI的灰度4 9 | 100: Color(0xFFf1f1f1), 10 | // 对应UI的灰度3 11 | 200: Color(0xFFe1e1e1), 12 | // 对应UI的灰度2 13 | 500: Color(_greyPrimaryValue), 14 | // 对应UI的灰度1 15 | 900: Color(0x00000000), 16 | }, 17 | ); 18 | const int _greyPrimaryValue = 0xFF9999999; 19 | 20 | class AppColors { 21 | AppColors._(); 22 | static const MaterialColor grey = Colors.grey; 23 | static const Color accentColor = Color(0xffd3c1fe); 24 | static const Color fontColor = Color(0xff201b1a); 25 | static const Color borderColor = Color(0xffeeeeee); 26 | static const Color surface = Color(0xffede8f8); 27 | static const Color background = Color(0xfff8f8f8); 28 | } 29 | -------------------------------------------------------------------------------- /lib/themes/color_schema_extension.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | extension ColorSchemaExtension on ColorScheme { 4 | static const Color _sidebar = Color(0xFFF0F0F0); 5 | static const Color _dark_sidebar = Color(0xFF202020); 6 | 7 | static const Color _divider_line = Color(0xFFF2F2F2); 8 | static const Color _divider_dark_line = Color(0xFF3B3B3B); 9 | 10 | static const Color _input_background = Color(0xFFF8F8F8); 11 | static const Color _dark_input_background = Color(0xFF1F1F1F); 12 | 13 | static const Color _mask = Color(0x00000000); 14 | static const Color _dark_mask = Color(0x4D000000); 15 | 16 | static const Color _text_1 = Color(0xFF262626); 17 | static const Color _dark_text_1 = Color(0xFFA8A8A8); 18 | 19 | static const Color _text_2 = Color(0xff4b5c76); 20 | // static const Color _text_2 = Color(0xFF595959); 21 | static const Color _dark_text_2 = Color(0xFFA8A8A8); 22 | 23 | static const Color _text_3 = Color(0xFF8C8C8C); 24 | static const Color _dark_text_3 = Color(0xFF8C8C8C); 25 | 26 | static const Color _text_4 = Color(0xFFBFBFBF); 27 | static const Color _dark_text_4 = Color(0xFF696969); 28 | 29 | static const Color _text_5 = Color(0xFFEFEFEF); 30 | static const Color _dark_text_5 = Color(0xFF4C4C4C); 31 | 32 | static const Color _text_6 = Color(0xFFFFFFFF); 33 | static const Color _dark_text_6 = Color(0xFFFFFFFF); 34 | 35 | static const Color _toast_text = Color(0xFFFFFFFF); 36 | static const Color _dark_toast_text = Color(0xFF1D1D1D); 37 | 38 | static const Color _toast_icon = Color(0xFFFFFFFF); 39 | static const Color _dark_toast_icon = Color(0xFF696969); 40 | 41 | static const Color _toast_background = Color(0xCC000000); 42 | static const Color _dark_toast_background = Color(0xCCFFFFFF); 43 | 44 | static const Color _dialog_cancel_background = Color(0xFFE6E6E6); 45 | static const Color _dark_dialog_cancel_background = Color(0xFF1F1F1F); 46 | 47 | static const Color _border_color = Color(0xFFE7E7E7); 48 | static const Color _dark_border_color = Color(0xFFE7E7E7); 49 | 50 | static const Color _material_shadow_color = Color(0x0F000000); 51 | static const Color _dark_material_shadow_color = Color(0x0F000000); 52 | 53 | static const Color _track_color = Color(0x40636363); 54 | static const Color _dark_track_color = Color(0x40636363); 55 | 56 | static const Color _sublist_background = Color(0xFFF5F5F8); 57 | static const Color _dark_sublist_background = Color(0xFF363636); 58 | 59 | static const Color _normal_button_background = Color(0xFFE4F6EC); 60 | static const Color _dark_normal_button_background = Color(0xFFE4F6EC); 61 | 62 | static const Color _imbar_icon_color = Color(0xFFB7B7B7); 63 | static const Color _dark_imbar_icon_color = Color(0xFFB7B7B7); 64 | 65 | static const Color _thrice_color = Color(0xFFFFAF64); 66 | static const Color _dark_thrice_color = Color(0xFFFFAF64); 67 | 68 | static const Color _on_thrice_color = Color(0xFFFFFFFF); 69 | static const Color _dark_on_thrice_color = Color(0xFFFFFFFF); 70 | 71 | Color get sidebar { 72 | if (brightness == Brightness.light) { 73 | return _sidebar; 74 | } 75 | 76 | return _dark_sidebar; 77 | } 78 | 79 | Color get dividerLine { 80 | if (brightness == Brightness.light) { 81 | return _divider_line; 82 | } 83 | 84 | return _divider_dark_line; 85 | } 86 | 87 | Color get inputBackground { 88 | if (brightness == Brightness.light) { 89 | return _input_background; 90 | } 91 | 92 | return _dark_input_background; 93 | } 94 | 95 | Color get mask { 96 | if (brightness == Brightness.light) { 97 | return _mask; 98 | } 99 | 100 | return _dark_mask; 101 | } 102 | 103 | Color get textTitle { 104 | if (brightness == Brightness.light) { 105 | return _text_1; 106 | } 107 | 108 | return _dark_text_1; 109 | } 110 | 111 | Color get textContent { 112 | if (brightness == Brightness.light) { 113 | return _text_2; 114 | } 115 | 116 | return _dark_text_2; 117 | } 118 | 119 | Color get textIconCaption { 120 | if (brightness == Brightness.light) { 121 | return _text_3; 122 | } 123 | 124 | return _dark_text_3; 125 | } 126 | 127 | Color get textCaption { 128 | if (brightness == Brightness.light) { 129 | return _text_4; 130 | } 131 | 132 | return _dark_text_4; 133 | } 134 | 135 | Color get textHit { 136 | if (brightness == Brightness.light) { 137 | return _text_5; 138 | } 139 | 140 | return _dark_text_5; 141 | } 142 | 143 | Color get textButton { 144 | if (brightness == Brightness.light) { 145 | return _text_6; 146 | } 147 | 148 | return _dark_text_6; 149 | } 150 | 151 | Color get toastText { 152 | if (brightness == Brightness.light) { 153 | return _toast_text; 154 | } 155 | 156 | return _dark_toast_text; 157 | } 158 | 159 | Color get toastIcon { 160 | if (brightness == Brightness.light) { 161 | return _toast_icon; 162 | } 163 | 164 | return _dark_toast_icon; 165 | } 166 | 167 | Color get toastBackground { 168 | if (brightness == Brightness.light) { 169 | return _toast_background; 170 | } 171 | 172 | return _dark_toast_background; 173 | } 174 | 175 | Color get dialogCancelBackground { 176 | if (brightness == Brightness.light) { 177 | return _dialog_cancel_background; 178 | } 179 | 180 | return _dark_dialog_cancel_background; 181 | } 182 | 183 | Color get barrierColor { 184 | return _dark_mask; 185 | } 186 | 187 | Color get borderColor { 188 | if (brightness == Brightness.light) { 189 | return _border_color; 190 | } 191 | 192 | return _dark_border_color; 193 | } 194 | 195 | Color get materialShadowColor { 196 | if (brightness == Brightness.light) { 197 | return _material_shadow_color; 198 | } 199 | 200 | return _dark_material_shadow_color; 201 | } 202 | 203 | Color get trackColor { 204 | if (brightness == Brightness.light) { 205 | return _track_color; 206 | } 207 | 208 | return _dark_track_color; 209 | } 210 | 211 | Color get sublistBackground { 212 | if (brightness == Brightness.light) { 213 | return _sublist_background; 214 | } 215 | 216 | return _dark_sublist_background; 217 | } 218 | 219 | Color get normalButtonBackground { 220 | if (brightness == Brightness.light) { 221 | return _normal_button_background; 222 | } 223 | 224 | return _dark_normal_button_background; 225 | } 226 | 227 | Color get imbarIconColor { 228 | if (brightness == Brightness.light) { 229 | return _imbar_icon_color; 230 | } 231 | 232 | return _dark_imbar_icon_color; 233 | } 234 | 235 | Color get thriceColor => 236 | brightness == Brightness.light ? _thrice_color : _dark_thrice_color; 237 | 238 | Color get onThriceColor => 239 | brightness == Brightness.light ? _on_thrice_color : _dark_on_thrice_color; 240 | } 241 | -------------------------------------------------------------------------------- /lib/themes/theme.dart: -------------------------------------------------------------------------------- 1 | export 'color_schema_extension.dart'; 2 | export 'default_theme_data.dart'; 3 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/xcuserdata/ 7 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import flutter_acrylic 9 | 10 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 11 | FlutterAcrylicPlugin.register(with: registry.registrar(forPlugin: "FlutterAcrylicPlugin")) 12 | } 13 | -------------------------------------------------------------------------------- /macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '10.11' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | end 35 | 36 | post_install do |installer| 37 | installer.pods_project.targets.each do |target| 38 | flutter_additional_macos_build_settings(target) 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /macos/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - flutter_acrylic (0.1.0): 3 | - FlutterMacOS 4 | - FlutterMacOS (1.0.0) 5 | 6 | DEPENDENCIES: 7 | - flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`) 8 | - FlutterMacOS (from `Flutter/ephemeral`) 9 | 10 | EXTERNAL SOURCES: 11 | flutter_acrylic: 12 | :path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos 13 | FlutterMacOS: 14 | :path: Flutter/ephemeral 15 | 16 | SPEC CHECKSUMS: 17 | flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17 18 | FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 19 | 20 | PODFILE CHECKSUM: 6eac6b3292e5142cfc23bdeb71848a40ec51c14c 21 | 22 | COCOAPODS: 1.11.3 23 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 73 | 79 | 80 | 81 | 82 | 84 | 85 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = termare_app 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.nightmare.termareApp 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2021 com.nightmare. All rights reserved. 15 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.cs.allow-jit 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import flutter_acrylic 4 | 5 | class MainFlutterWindow: NSWindow { 6 | override func awakeFromNib() { 7 | let windowFrame = self.frame 8 | let blurryContainerViewController = BlurryContainerViewController() 9 | self.contentViewController = blurryContainerViewController 10 | self.setFrame(windowFrame, display: true) 11 | 12 | /* Initialize the flutter_acrylic plugin */ 13 | MainFlutterWindowManipulator.start(mainFlutterWindow: self) 14 | 15 | RegisterGeneratedPlugins(registry: blurryContainerViewController.flutterViewController) 16 | super.awakeFromNib() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: 4 | archive: 5 | dependency: "direct main" 6 | description: 7 | name: archive 8 | url: "https://pub.flutter-io.cn" 9 | source: hosted 10 | version: "3.3.2" 11 | async: 12 | dependency: transitive 13 | description: 14 | name: async 15 | url: "https://pub.flutter-io.cn" 16 | source: hosted 17 | version: "2.9.0" 18 | boolean_selector: 19 | dependency: transitive 20 | description: 21 | name: boolean_selector 22 | url: "https://pub.flutter-io.cn" 23 | source: hosted 24 | version: "2.1.0" 25 | characters: 26 | dependency: transitive 27 | description: 28 | name: characters 29 | url: "https://pub.flutter-io.cn" 30 | source: hosted 31 | version: "1.2.1" 32 | clock: 33 | dependency: transitive 34 | description: 35 | name: clock 36 | url: "https://pub.flutter-io.cn" 37 | source: hosted 38 | version: "1.1.1" 39 | collection: 40 | dependency: transitive 41 | description: 42 | name: collection 43 | url: "https://pub.flutter-io.cn" 44 | source: hosted 45 | version: "1.16.0" 46 | convert: 47 | dependency: transitive 48 | description: 49 | name: convert 50 | url: "https://pub.flutter-io.cn" 51 | source: hosted 52 | version: "3.1.1" 53 | crypto: 54 | dependency: transitive 55 | description: 56 | name: crypto 57 | url: "https://pub.flutter-io.cn" 58 | source: hosted 59 | version: "3.0.2" 60 | cupertino_icons: 61 | dependency: "direct main" 62 | description: 63 | name: cupertino_icons 64 | url: "https://pub.flutter-io.cn" 65 | source: hosted 66 | version: "1.0.5" 67 | dart_pty: 68 | dependency: transitive 69 | description: 70 | path: "." 71 | ref: HEAD 72 | resolved-ref: a437347d882e8e9110564cef9495f8dafc6c8b89 73 | url: "https://github.com/Termare/dart_pty" 74 | source: git 75 | version: "0.0.3" 76 | dio: 77 | dependency: "direct main" 78 | description: 79 | name: dio 80 | url: "https://pub.flutter-io.cn" 81 | source: hosted 82 | version: "4.0.6" 83 | equatable: 84 | dependency: transitive 85 | description: 86 | name: equatable 87 | url: "https://pub.flutter-io.cn" 88 | source: hosted 89 | version: "2.0.5" 90 | event_bus: 91 | dependency: transitive 92 | description: 93 | name: event_bus 94 | url: "https://pub.flutter-io.cn" 95 | source: hosted 96 | version: "1.1.1" 97 | fake_async: 98 | dependency: transitive 99 | description: 100 | name: fake_async 101 | url: "https://pub.flutter-io.cn" 102 | source: hosted 103 | version: "1.3.1" 104 | ffi: 105 | dependency: transitive 106 | description: 107 | name: ffi 108 | url: "https://pub.flutter-io.cn" 109 | source: hosted 110 | version: "1.2.1" 111 | flutter: 112 | dependency: "direct main" 113 | description: flutter 114 | source: sdk 115 | version: "0.0.0" 116 | flutter_acrylic: 117 | dependency: "direct main" 118 | description: 119 | name: flutter_acrylic 120 | url: "https://pub.flutter-io.cn" 121 | source: hosted 122 | version: "1.0.0+2" 123 | flutter_test: 124 | dependency: "direct dev" 125 | description: flutter 126 | source: sdk 127 | version: "0.0.0" 128 | get: 129 | dependency: "direct main" 130 | description: 131 | name: get 132 | url: "https://pub.flutter-io.cn" 133 | source: hosted 134 | version: "4.6.5" 135 | global_repository: 136 | dependency: "direct main" 137 | description: 138 | path: "." 139 | ref: HEAD 140 | resolved-ref: "5a1f3d90c0d1abff1065b593154de2f15dafaa64" 141 | url: "https://github.com/nightmare-space/global_repository" 142 | source: git 143 | version: "0.0.1" 144 | http_parser: 145 | dependency: transitive 146 | description: 147 | name: http_parser 148 | url: "https://pub.flutter-io.cn" 149 | source: hosted 150 | version: "4.0.2" 151 | matcher: 152 | dependency: transitive 153 | description: 154 | name: matcher 155 | url: "https://pub.flutter-io.cn" 156 | source: hosted 157 | version: "0.12.12" 158 | material_color_utilities: 159 | dependency: transitive 160 | description: 161 | name: material_color_utilities 162 | url: "https://pub.flutter-io.cn" 163 | source: hosted 164 | version: "0.1.5" 165 | meta: 166 | dependency: transitive 167 | description: 168 | name: meta 169 | url: "https://pub.flutter-io.cn" 170 | source: hosted 171 | version: "1.8.0" 172 | path: 173 | dependency: transitive 174 | description: 175 | name: path 176 | url: "https://pub.flutter-io.cn" 177 | source: hosted 178 | version: "1.8.2" 179 | permission_handler: 180 | dependency: transitive 181 | description: 182 | name: permission_handler 183 | url: "https://pub.flutter-io.cn" 184 | source: hosted 185 | version: "6.0.0" 186 | permission_handler_platform_interface: 187 | dependency: transitive 188 | description: 189 | name: permission_handler_platform_interface 190 | url: "https://pub.flutter-io.cn" 191 | source: hosted 192 | version: "3.9.0" 193 | platform_info: 194 | dependency: transitive 195 | description: 196 | name: platform_info 197 | url: "https://pub.flutter-io.cn" 198 | source: hosted 199 | version: "3.2.0" 200 | plugin_platform_interface: 201 | dependency: transitive 202 | description: 203 | name: plugin_platform_interface 204 | url: "https://pub.flutter-io.cn" 205 | source: hosted 206 | version: "2.1.3" 207 | pseudo_terminal_utils: 208 | dependency: "direct main" 209 | description: 210 | path: "." 211 | ref: HEAD 212 | resolved-ref: "90d635ced306dc4237171da20ce497fd12134902" 213 | url: "https://github.com/Termare/pseudo_terminal_utils" 214 | source: git 215 | version: "0.0.1" 216 | pty: 217 | dependency: "direct main" 218 | description: 219 | path: "." 220 | ref: HEAD 221 | resolved-ref: "5c3798fef3f304316a8c8b8b66d611c944213dac" 222 | url: "https://github.com/TerminalStudio/pty" 223 | source: git 224 | version: "0.2.2-pre" 225 | quiver: 226 | dependency: transitive 227 | description: 228 | name: quiver 229 | url: "https://pub.flutter-io.cn" 230 | source: hosted 231 | version: "3.1.0" 232 | signale: 233 | dependency: transitive 234 | description: 235 | name: signale 236 | url: "https://pub.flutter-io.cn" 237 | source: hosted 238 | version: "0.0.8" 239 | sky_engine: 240 | dependency: transitive 241 | description: flutter 242 | source: sdk 243 | version: "0.0.99" 244 | source_span: 245 | dependency: transitive 246 | description: 247 | name: source_span 248 | url: "https://pub.flutter-io.cn" 249 | source: hosted 250 | version: "1.9.0" 251 | stack_trace: 252 | dependency: transitive 253 | description: 254 | name: stack_trace 255 | url: "https://pub.flutter-io.cn" 256 | source: hosted 257 | version: "1.10.0" 258 | stream_channel: 259 | dependency: transitive 260 | description: 261 | name: stream_channel 262 | url: "https://pub.flutter-io.cn" 263 | source: hosted 264 | version: "2.1.0" 265 | string_scanner: 266 | dependency: transitive 267 | description: 268 | name: string_scanner 269 | url: "https://pub.flutter-io.cn" 270 | source: hosted 271 | version: "1.1.1" 272 | synchronized: 273 | dependency: transitive 274 | description: 275 | name: synchronized 276 | url: "https://pub.flutter-io.cn" 277 | source: hosted 278 | version: "3.0.0+3" 279 | term_glyph: 280 | dependency: transitive 281 | description: 282 | name: term_glyph 283 | url: "https://pub.flutter-io.cn" 284 | source: hosted 285 | version: "1.2.1" 286 | test_api: 287 | dependency: transitive 288 | description: 289 | name: test_api 290 | url: "https://pub.flutter-io.cn" 291 | source: hosted 292 | version: "0.4.12" 293 | typed_data: 294 | dependency: transitive 295 | description: 296 | name: typed_data 297 | url: "https://pub.flutter-io.cn" 298 | source: hosted 299 | version: "1.3.1" 300 | vector_math: 301 | dependency: transitive 302 | description: 303 | name: vector_math 304 | url: "https://pub.flutter-io.cn" 305 | source: hosted 306 | version: "2.1.2" 307 | vibration: 308 | dependency: "direct main" 309 | description: 310 | name: vibration 311 | url: "https://pub.flutter-io.cn" 312 | source: hosted 313 | version: "1.7.6" 314 | webview_flutter: 315 | dependency: "direct main" 316 | description: 317 | name: webview_flutter 318 | url: "https://pub.flutter-io.cn" 319 | source: hosted 320 | version: "2.8.0" 321 | webview_flutter_android: 322 | dependency: transitive 323 | description: 324 | name: webview_flutter_android 325 | url: "https://pub.flutter-io.cn" 326 | source: hosted 327 | version: "2.10.4" 328 | webview_flutter_platform_interface: 329 | dependency: transitive 330 | description: 331 | name: webview_flutter_platform_interface 332 | url: "https://pub.flutter-io.cn" 333 | source: hosted 334 | version: "1.9.5" 335 | webview_flutter_wkwebview: 336 | dependency: transitive 337 | description: 338 | name: webview_flutter_wkwebview 339 | url: "https://pub.flutter-io.cn" 340 | source: hosted 341 | version: "2.9.5" 342 | win32: 343 | dependency: transitive 344 | description: 345 | name: win32 346 | url: "https://pub.flutter-io.cn" 347 | source: hosted 348 | version: "2.6.1" 349 | xterm: 350 | dependency: "direct main" 351 | description: 352 | path: "." 353 | ref: HEAD 354 | resolved-ref: cb0de8b55858cee8261ca3676074851eb4beb7c2 355 | url: "https://github.com/TerminalStudio/xterm.dart" 356 | source: git 357 | version: "3.2.7" 358 | sdks: 359 | dart: ">=2.18.0 <3.0.0" 360 | flutter: ">=3.0.0" 361 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: termare_app 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.9.0 <3.0.0" 10 | 11 | dependencies: 12 | xterm: 13 | git: https://github.com/TerminalStudio/xterm.dart 14 | 15 | flutter_acrylic: ^1.0.0 16 | pty: 17 | git: https://github.com/TerminalStudio/pty 18 | vibration: ^1.7.3 19 | archive: ^3.1.2 20 | get: ^4.1.4 21 | flutter: 22 | sdk: flutter 23 | # just_audio: ^0.9.5 24 | global_repository: 25 | git: https://github.com/nightmare-space/global_repository 26 | cupertino_icons: ^1.0.2 27 | dio: ^4.0.0 28 | webview_flutter: ^2.0.12 29 | pseudo_terminal_utils: 30 | git: https://github.com/Termare/pseudo_terminal_utils 31 | dev_dependencies: 32 | flutter_test: 33 | sdk: flutter 34 | 35 | 36 | flutter: 37 | uses-material-design: true 38 | fonts: 39 | - family: SourceCodePro 40 | fonts: 41 | - asset: assets/fonts/SourceCodePro.ttf 42 | - family: SourceCodeProMediumforPowerline 43 | fonts: 44 | - asset: assets/fonts/SourceCodeProMediumforPowerline.otf 45 | - family: MesloLGMforPowerline 46 | fonts: 47 | - asset: assets/fonts/MesloLGMforPowerline.ttf 48 | - family: MenloforPowerline 49 | fonts: 50 | - asset: assets/fonts/MenloforPowerline.ttf 51 | - family: DroidSansMono 52 | fonts: 53 | - asset: assets/fonts/DroidSansMono.ttf 54 | 55 | assets: 56 | - assets/ogg/ 57 | - assets/icons/ 58 | - assets/lib/ 59 | - assets/text/ 60 | 61 | 62 | dependency_overrides: 63 | # xterm: 64 | # path: /Users/nightmare/Desktop/TerminalStudio/xterm.dart -------------------------------------------------------------------------------- /screencap/cmatrix-r.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/cmatrix-r.jpg -------------------------------------------------------------------------------- /screencap/cmatrix.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/cmatrix.jpg -------------------------------------------------------------------------------- /screencap/dart-version.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/dart-version.jpg -------------------------------------------------------------------------------- /screencap/htop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/htop.jpg -------------------------------------------------------------------------------- /screencap/mac-neofetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/mac-neofetch.png -------------------------------------------------------------------------------- /screencap/nano.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/nano.jpg -------------------------------------------------------------------------------- /screencap/oh_my_zsh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/oh_my_zsh.jpg -------------------------------------------------------------------------------- /screencap/select-page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/select-page.jpg -------------------------------------------------------------------------------- /screencap/setting-page-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/setting-page-01.jpg -------------------------------------------------------------------------------- /screencap/setting-page-02.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/setting-page-02.jpg -------------------------------------------------------------------------------- /screencap/sl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/sl.jpg -------------------------------------------------------------------------------- /screencap/vim.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/screencap/vim.jpg -------------------------------------------------------------------------------- /scripts/build_macos.sh: -------------------------------------------------------------------------------- 1 | flutter build macos -------------------------------------------------------------------------------- /scripts/build_windows.bat: -------------------------------------------------------------------------------- 1 | flutter build windows -------------------------------------------------------------------------------- /scripts/clean.sh: -------------------------------------------------------------------------------- 1 | flutter clean -------------------------------------------------------------------------------- /scripts/generate_mac_app.sh: -------------------------------------------------------------------------------- 1 | flutter build macos 2 | rm -rf ./build/macos/Build/Products/Release/移动到这 3 | ln -s -f /Applications ./build/macos/Build/Products/Release/移动到这 4 | tar -zcvf ./Termare.tar -C ./build/macos/Build/Products/ Release/Termare.app/ Release/移动到这 5 | rm -rf ./build/macos/Build/Products/Release/移动到这 -------------------------------------------------------------------------------- /scripts/patch_executable.sh: -------------------------------------------------------------------------------- 1 | cp ./executable/macos/adb ./build/macos/Build/Products/Release/adb_tool.app/Contents/MacOS/data/usr/bin/ 2 | mkdir -p ./build/macos/Build/Products/Release/adb_tool.app/Contents/MacOS/data/usr/bin 3 | cp ./executable/macos/adb ./build/macos/Build/Products/Debug/adb_tool.app/Contents/MacOS/data/usr/bin/ -------------------------------------------------------------------------------- /scripts/properties.sh: -------------------------------------------------------------------------------- 1 | VERSION='1.0.0' 2 | TARGET_PATH=root@$server:/home/nightmare/YanTool/resources/Termare 3 | APP_NAME='Termare' -------------------------------------------------------------------------------- /scripts/run_release.sh: -------------------------------------------------------------------------------- 1 | flutter run --release -------------------------------------------------------------------------------- /scripts/upload/upload.sh: -------------------------------------------------------------------------------- 1 | LOCAL_DIR=$(cd `dirname $0`; pwd) 2 | PROJECT_DIR=$LOCAL_DIR/../.. 3 | source $LOCAL_DIR/../properties.sh 4 | echo $PROJECT_DIR 5 | if [ -f $PROJECT_DIR/$app_name'_macOS.tar' ]; then 6 | rsync -v $PROJECT_DIR/$app_name'_macOS.tar' $TARGET_PATH'/'$app_name'_'$version'_macOS'.tar 7 | fi 8 | rsync -v $PROJECT_DIR/build/app/outputs/flutter-apk/app-release.apk $TARGET_PATH/$APP_NAME'_'$VERSION'_'Android_arm64.apk 9 | -------------------------------------------------------------------------------- /test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility that Flutter provides. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:termare_app/main.dart'; 12 | 13 | void main() { 14 | // testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // // Build our app and trigger a frame. 16 | // await tester.pumpWidget(const MyApp()); 17 | 18 | // // Verify that our counter starts at 0. 19 | // expect(find.text('0'), findsOneWidget); 20 | // expect(find.text('1'), findsNothing); 21 | 22 | // // Tap the '+' icon and trigger a frame. 23 | // await tester.tap(find.byIcon(Icons.add)); 24 | // await tester.pump(); 25 | 26 | // // Verify that our counter has incremented. 27 | // expect(find.text('0'), findsNothing); 28 | // expect(find.text('1'), findsOneWidget); 29 | // }); 30 | } 31 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/web/favicon.png -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Termare/termare_app/37543659928881391ead872e8ab59805d91e8ddc/web/icons/Icon-512.png -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | termare_app 30 | 31 | 32 | 33 | 36 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "termare_app", 3 | "short_name": "termare_app", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | } 22 | ] 23 | } 24 | --------------------------------------------------------------------------------