| | |
| | | |
| | | public final static String HOST = "http://xxx"; |
| | | |
| | | public final static String DOWNLOAD_DIR_NAME = "xxx"; |
| | | |
| | | public final static boolean isDisableProxy = false; |
| | | |
| | | public static final String USER_AGREEMENT = "http://h5.hanju.goxcw.com/hanju/user_protocol.html"; |
| | |
| | | |
| | | import android.Manifest; |
| | | import android.app.Activity; |
| | | import android.app.Dialog; |
| | | import android.content.Context; |
| | | import android.content.Intent; |
| | | import android.content.pm.PackageManager; |
| | |
| | | import android.widget.TextView; |
| | | import android.widget.Toast; |
| | | |
| | | import com.demo.app.utils.Constant; |
| | | import com.demo.app.utils.JumpActivityUtil; |
| | | import com.demo.lib.common.dialog.DialogUtil; |
| | | import com.demo.lib.common.util.ui.LoadingDialogUtil; |
| | | import com.demo.library_ec.AlibcTradeUtil; |
| | | import com.demo.lib.common.util.Environment; |
| | | import com.demo.lib.common.util.common.StringUtils; |
| | |
| | | ImageView iv_right; |
| | | WebView webview; |
| | | private boolean boo = false; |
| | | private Dialog loadingDialog; |
| | | |
| | | public MyJavaInterface(Activity activity, WebView webview) { |
| | | super(activity); |
| | | mContext = activity; |
| | | this.webview = webview; |
| | | boo = true; |
| | | loadingDialog = LoadingDialogUtil.getLoadingDialog(activity, ""); |
| | | } |
| | | |
| | | public MyJavaInterface(Activity activity, TextView tv_top_bar_middle |
| | |
| | | this.tv_top_bar_right = tv_top_bar_right; |
| | | this.iv_right = iv_right; |
| | | this.webview = webview; |
| | | loadingDialog = LoadingDialogUtil.getLoadingDialog(activity, ""); |
| | | } |
| | | |
| | | @JavascriptInterface |
| | |
| | | AlibcTradeUtil.openAuthLink(mContext, url); |
| | | } |
| | | |
| | | @JavascriptInterface |
| | | public void showLoading() { |
| | | |
| | | mContext.runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | DialogUtil.show(loadingDialog); |
| | | } |
| | | }); |
| | | |
| | | } |
| | | |
| | | @JavascriptInterface |
| | | public void hideLoading() { |
| | | mContext.runOnUiThread(new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | DialogUtil.dismiss(loadingDialog); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 判断权限集合 是否授权 false授权 true未授权 |
| | | public boolean lacksPermissions(String... permissions) { |
| | | for (String permission : permissions) { |
| | |
| | | ActivityCompat.requestPermissions(mContext, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}, 10023); |
| | | } else {//存储权限已开 |
| | | String md5 = MD5Utils.getMD532(url); |
| | | String path = Environment.getExternalStorageDirectory() |
| | | + "/hanju"; |
| | | String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) |
| | | + "/" + Constant.DOWNLOAD_DIR_NAME; |
| | | if (!new File(path).exists()) { |
| | | new File(path).mkdirs(); |
| | | } |
| | | |
| | | File file = new File(path + "/" + md5 + ".jpg"); |
| | | if (!file.exists()) { |
| | | try { |
| | |
| | | int attr selectableItemBackground 0x0 |
| | | int attr selectableItemBackgroundBorderless 0x0 |
| | | int attr shelfBackground 0x0 |
| | | int attr shimmer_angle 0x0 |
| | | int attr shimmer_animation_duration 0x0 |
| | | int attr shimmer_auto_start 0x0 |
| | | int attr shimmer_color 0x0 |
| | | int attr shimmer_gradient_center_color_width 0x0 |
| | | int attr shimmer_mask_width 0x0 |
| | | int attr shimmer_reverse_animation 0x0 |
| | | int attr showAsAction 0x0 |
| | | int attr showDividers 0x0 |
| | | int attr showMotionSpec 0x0 |
| | |
| | | int color bright_foreground_material_light 0x0 |
| | | int color button_material_dark 0x0 |
| | | int color button_material_light 0x0 |
| | | int color by_footer_text_loading 0x0 |
| | | int color by_skeleton_light_transparent 0x0 |
| | | int color by_skeleton_shimmer_color 0x0 |
| | | int color cardview_dark_background 0x0 |
| | | int color cardview_light_background 0x0 |
| | | int color cardview_shadow_end_color 0x0 |
| | |
| | | int dimen abc_text_size_subtitle_material_toolbar 0x0 |
| | | int dimen abc_text_size_title_material 0x0 |
| | | int dimen abc_text_size_title_material_toolbar 0x0 |
| | | int dimen by_load_more_simple_height 0x0 |
| | | int dimen by_load_more_simple_margin 0x0 |
| | | int dimen by_progress_width_height 0x0 |
| | | int dimen by_refresh_simple_height 0x0 |
| | | int dimen by_refresh_simple_margin 0x0 |
| | | int dimen cardview_compat_inset_shadow 0x0 |
| | | int dimen cardview_default_elevation 0x0 |
| | | int dimen cardview_default_radius 0x0 |
| | |
| | | int drawable btn_radio_off_to_on_mtrl_animation 0x0 |
| | | int drawable btn_radio_on_mtrl 0x0 |
| | | int drawable btn_radio_on_to_off_mtrl_animation 0x0 |
| | | int drawable by_progress_rotate 0x0 |
| | | int drawable by_refresh_arrow 0x0 |
| | | int drawable color_progressbar 0x0 |
| | | int drawable design_bottom_navigation_item_background 0x0 |
| | | int drawable design_fab_background 0x0 |
| | |
| | | int id glide_custom_view_target_tag 0x0 |
| | | int id group_divider 0x0 |
| | | int id gv_emotion 0x0 |
| | | int id header_content 0x0 |
| | | int id home 0x0 |
| | | int id homeAsUp 0x0 |
| | | int id horizontal 0x0 |
| | | int id icon 0x0 |
| | | int id icon_group 0x0 |
| | | int id id_by_sticky_item 0x0 |
| | | int id ifRoom 0x0 |
| | | int id image 0x0 |
| | | int id info 0x0 |
| | | int id italic 0x0 |
| | | int id item_touch_helper_previous_elevation 0x0 |
| | | int id iv_arrow 0x0 |
| | | int id labeled 0x0 |
| | | int id largeLabel 0x0 |
| | | int id left 0x0 |
| | |
| | | int id line3 0x0 |
| | | int id listMode 0x0 |
| | | int id list_item 0x0 |
| | | int id ll_more_loading 0x0 |
| | | int id main_content 0x0 |
| | | int id masked 0x0 |
| | | int id media_actions 0x0 |
| | |
| | | int id parentPanel 0x0 |
| | | int id parent_matrix 0x0 |
| | | int id pause 0x0 |
| | | int id pb_progress 0x0 |
| | | int id pin 0x0 |
| | | int id prev 0x0 |
| | | int id progress_circular 0x0 |
| | |
| | | int id transition_position 0x0 |
| | | int id transition_scene_layoutid_cache 0x0 |
| | | int id transition_transform 0x0 |
| | | int id tv_more_failed 0x0 |
| | | int id tv_msg 0x0 |
| | | int id tv_no_more 0x0 |
| | | int id tv_refresh_tip 0x0 |
| | | int id unchecked 0x0 |
| | | int id uniform 0x0 |
| | | int id unlabeled 0x0 |
| | | int id up 0x0 |
| | | int id useLogo 0x0 |
| | | int id vertical 0x0 |
| | | int id view_bottom 0x0 |
| | | int id view_offset_helper 0x0 |
| | | int id visible 0x0 |
| | | int id webview_player 0x0 |
| | |
| | | int layout emotion_grid 0x0 |
| | | int layout emotion_item 0x0 |
| | | int layout fragment_webview_video 0x0 |
| | | int layout layout_by_default_item_skeleton 0x0 |
| | | int layout layout_by_skeleton_shimmer 0x0 |
| | | int layout listview_footer 0x0 |
| | | int layout media_controller 0x0 |
| | | int layout mtrl_layout_snackbar 0x0 |
| | |
| | | int layout select_dialog_item_material 0x0 |
| | | int layout select_dialog_multichoice_material 0x0 |
| | | int layout select_dialog_singlechoice_material 0x0 |
| | | int layout simple_by_load_more_view 0x0 |
| | | int layout simple_by_refresh_view 0x0 |
| | | int layout support_simple_spinner_dropdown_item 0x0 |
| | | int string abc_action_bar_home_description 0x0 |
| | | int string abc_action_bar_up_description 0x0 |
| | |
| | | int string app_name 0x0 |
| | | int string appbar_scrolling_view_behavior 0x0 |
| | | int string bottom_sheet_behavior 0x0 |
| | | int string by_footer_load_failed 0x0 |
| | | int string by_footer_loading 0x0 |
| | | int string by_footer_no_more 0x0 |
| | | int string by_header_hint_normal 0x0 |
| | | int string by_header_hint_release 0x0 |
| | | int string by_refresh_done 0x0 |
| | | int string by_refreshing 0x0 |
| | | int string character_counter_content_description 0x0 |
| | | int string character_counter_pattern 0x0 |
| | | int string fab_transformation_scrim_behavior 0x0 |
| | |
| | | int styleable SearchView_voiceIcon 16 |
| | | int[] styleable ShelvesView { 0x0 } |
| | | int styleable ShelvesView_shelfBackground 0 |
| | | int[] styleable ShimmerLayout { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } |
| | | int styleable ShimmerLayout_shimmer_angle 0 |
| | | int styleable ShimmerLayout_shimmer_animation_duration 1 |
| | | int styleable ShimmerLayout_shimmer_auto_start 2 |
| | | int styleable ShimmerLayout_shimmer_color 3 |
| | | int styleable ShimmerLayout_shimmer_gradient_center_color_width 4 |
| | | int styleable ShimmerLayout_shimmer_mask_width 5 |
| | | int styleable ShimmerLayout_shimmer_reverse_animation 6 |
| | | int[] styleable SlidingMenu { 0x0 } |
| | | int styleable SlidingMenu_rightPadding 0 |
| | | int[] styleable Snackbar { 0x0, 0x0 } |
| | |
| | | attr selectableItemBackground |
| | | attr selectableItemBackgroundBorderless |
| | | attr shelfBackground |
| | | attr shimmer_angle |
| | | attr shimmer_animation_duration |
| | | attr shimmer_auto_start |
| | | attr shimmer_color |
| | | attr shimmer_gradient_center_color_width |
| | | attr shimmer_mask_width |
| | | attr shimmer_reverse_animation |
| | | attr showAsAction |
| | | attr showDividers |
| | | attr showMotionSpec |
| | |
| | | color bright_foreground_material_light |
| | | color button_material_dark |
| | | color button_material_light |
| | | color by_footer_text_loading |
| | | color by_skeleton_light_transparent |
| | | color by_skeleton_shimmer_color |
| | | color cardview_dark_background |
| | | color cardview_light_background |
| | | color cardview_shadow_end_color |
| | |
| | | dimen abc_text_size_subtitle_material_toolbar |
| | | dimen abc_text_size_title_material |
| | | dimen abc_text_size_title_material_toolbar |
| | | dimen by_load_more_simple_height |
| | | dimen by_load_more_simple_margin |
| | | dimen by_progress_width_height |
| | | dimen by_refresh_simple_height |
| | | dimen by_refresh_simple_margin |
| | | dimen cardview_compat_inset_shadow |
| | | dimen cardview_default_elevation |
| | | dimen cardview_default_radius |
| | |
| | | drawable btn_radio_off_to_on_mtrl_animation |
| | | drawable btn_radio_on_mtrl |
| | | drawable btn_radio_on_to_off_mtrl_animation |
| | | drawable by_progress_rotate |
| | | drawable by_refresh_arrow |
| | | drawable color_progressbar |
| | | drawable design_bottom_navigation_item_background |
| | | drawable design_fab_background |
| | |
| | | id glide_custom_view_target_tag |
| | | id group_divider |
| | | id gv_emotion |
| | | id header_content |
| | | id home |
| | | id homeAsUp |
| | | id horizontal |
| | | id icon |
| | | id icon_group |
| | | id id_by_sticky_item |
| | | id ifRoom |
| | | id image |
| | | id info |
| | | id italic |
| | | id item_touch_helper_previous_elevation |
| | | id iv_arrow |
| | | id labeled |
| | | id largeLabel |
| | | id left |
| | |
| | | id line3 |
| | | id listMode |
| | | id list_item |
| | | id ll_more_loading |
| | | id main_content |
| | | id masked |
| | | id media_actions |
| | |
| | | id parentPanel |
| | | id parent_matrix |
| | | id pause |
| | | id pb_progress |
| | | id pin |
| | | id prev |
| | | id progress_circular |
| | |
| | | id transition_position |
| | | id transition_scene_layoutid_cache |
| | | id transition_transform |
| | | id tv_more_failed |
| | | id tv_msg |
| | | id tv_no_more |
| | | id tv_refresh_tip |
| | | id unchecked |
| | | id uniform |
| | | id unlabeled |
| | | id up |
| | | id useLogo |
| | | id vertical |
| | | id view_bottom |
| | | id view_offset_helper |
| | | id visible |
| | | id webview_player |
| | |
| | | layout emotion_grid |
| | | layout emotion_item |
| | | layout fragment_webview_video |
| | | layout layout_by_default_item_skeleton |
| | | layout layout_by_skeleton_shimmer |
| | | layout listview_footer |
| | | layout media_controller |
| | | layout mtrl_layout_snackbar |
| | |
| | | layout select_dialog_item_material |
| | | layout select_dialog_multichoice_material |
| | | layout select_dialog_singlechoice_material |
| | | layout simple_by_load_more_view |
| | | layout simple_by_refresh_view |
| | | layout support_simple_spinner_dropdown_item |
| | | string abc_action_bar_home_description |
| | | string abc_action_bar_up_description |
| | |
| | | string app_name |
| | | string appbar_scrolling_view_behavior |
| | | string bottom_sheet_behavior |
| | | string by_footer_load_failed |
| | | string by_footer_loading |
| | | string by_footer_no_more |
| | | string by_header_hint_normal |
| | | string by_header_hint_release |
| | | string by_refresh_done |
| | | string by_refreshing |
| | | string character_counter_content_description |
| | | string character_counter_pattern |
| | | string fab_transformation_scrim_behavior |
| | |
| | | styleable ScrollingViewBehavior_Layout behavior_overlapTop |
| | | styleable SearchView android_focusable android_imeOptions android_inputType android_maxWidth closeIcon commitIcon defaultQueryHint goIcon iconifiedByDefault layout queryBackground queryHint searchHintIcon searchIcon submitBackground suggestionRowLayout voiceIcon |
| | | styleable ShelvesView shelfBackground |
| | | styleable ShimmerLayout shimmer_angle shimmer_animation_duration shimmer_auto_start shimmer_color shimmer_gradient_center_color_width shimmer_mask_width shimmer_reverse_animation |
| | | styleable SlidingMenu rightPadding |
| | | styleable Snackbar snackbarButtonStyle snackbarStyle |
| | | styleable SnackbarLayout android_maxWidth elevation maxActionInlineWidth |
| | |
| | | com.demo.lib.common.util.common.ConnectionUtils$3 |
| | | com/demo/lib/common/DatabaseContext.java |
| | | com.demo.lib.common.DatabaseContext |
| | | com/demo/lib/common/util/ui/LoadingDialogUtil.java |
| | | com.demo.lib.common.util.ui.LoadingDialogUtil |
| | | com/demo/lib/common/okhttp/request/PostFormRequest.java |
| | | com.demo.lib.common.okhttp.request.PostFormRequest |
| | | com.demo.lib.common.okhttp.request.PostFormRequest$1 |
| | | com.demo.lib.common.okhttp.request.PostFormRequest$1$1 |
| | | com/demo/lib/common/util/FragmentSwitchHelper.java |
| | | com.demo.lib.common.util.FragmentSwitchHelper |
| | | com/demo/lib/common/util/device/MobileUtil.java |
| | |
| | | com.demo.lib.common.okhttp.builder.HeadBuilder |
| | | com/demo/lib/common/util/common/DimenUtils.java |
| | | com.demo.lib.common.util.common.DimenUtils |
| | | com/demo/lib/common/dialog/BottomDialog.java |
| | | com.demo.lib.common.dialog.BottomDialog |
| | | com/demo/lib/common/okhttp/utils/L.java |
| | | com.demo.lib.common.okhttp.utils.L |
| | | com/demo/lib/common/okhttp/builder/OtherRequestBuilder.java |
| | | com.demo.lib.common.okhttp.builder.OtherRequestBuilder |
| | | com/demo/lib/common/widget/ShelfView.java |
| | | com.demo.lib.common.widget.ShelfView |
| | | com/demo/lib/common/widget/TagCloudLayout.java |
| | | com.demo.lib.common.widget.TagCloudLayout |
| | | com.demo.lib.common.widget.TagCloudLayout$FlingRunnable |
| | | com.demo.lib.common.widget.TagCloudLayout$OnScrollListener |
| | | com.demo.lib.common.widget.TagCloudLayout$TagView |
| | | com/demo/lib/common/util/ManifestDataUtil.java |
| | | com.demo.lib.common.util.ManifestDataUtil |
| | | com/demo/lib/common/util/SingleToast.java |
| | | com.demo.lib.common.util.SingleToast |
| | | com.demo.lib.common.util.SingleToast$1 |
| | | com/demo/lib/common/dialog/SlidingDialog.java |
| | | com.demo.lib.common.dialog.SlidingDialog |
| | | com/demo/lib/common/okhttp/utils/Platform.java |
| | | com.demo.lib.common.okhttp.utils.Platform |
| | | com.demo.lib.common.okhttp.utils.Platform$Android |
| | | com.demo.lib.common.okhttp.utils.Platform$Android$MainThreadExecutor |
| | | com/demo/lib/common/okhttp/log/LoggerInterceptor.java |
| | | com.demo.lib.common.okhttp.log.LoggerInterceptor |
| | | com/demo/lib/common/util/common/SoftKeyboardUtils.java |
| | | com.demo.lib.common.util.common.SoftKeyboardUtils |
| | | com/demo/lib/common/emotion/EmotionEditText.java |
| | | com.demo.lib.common.emotion.EmotionEditText |
| | | com/demo/lib/common/widget/verticalviewpager/ExtendedWebView.java |
| | | com.demo.lib.common.widget.verticalviewpager.ExtendedWebView |
| | | com/demo/lib/common/util/MarketUtils.java |
| | | com.demo.lib.common.util.MarketUtils |
| | | com/demo/lib/common/upgrade/Version.java |
| | |
| | | com.demo.lib.common.okhttp.builder.PostStringBuilder |
| | | com/demo/lib/common/okhttp/request/RequestCall.java |
| | | com.demo.lib.common.okhttp.request.RequestCall |
| | | com/demo/lib/common/drawable/SpotlightDrawable.java |
| | | com.demo.lib.common.drawable.SpotlightDrawable |
| | | com/demo/lib/common/util/common/StringUtils.java |
| | | com.demo.lib.common.util.common.StringUtils |
| | | com/lcjian/lcjianlibrary/BuildConfig.java |
| | | com.lcjian.lcjianlibrary.BuildConfig |
| | | com/demo/lib/common/okhttp/request/PostFileRequest.java |
| | |
| | | com/demo/lib/common/util/cache/StrictLineReader.java |
| | | com.demo.lib.common.util.cache.StrictLineReader |
| | | com.demo.lib.common.util.cache.StrictLineReader$1 |
| | | com/demo/lib/common/emotion/EmotionTextView.java |
| | | com.demo.lib.common.emotion.EmotionTextView |
| | | com/demo/lib/common/widget/MyGridView.java |
| | | com.demo.lib.common.widget.MyGridView |
| | | com/demo/lib/common/entity/IsSeeking.java |
| | | com.demo.lib.common.entity.IsSeeking |
| | | com/demo/lib/common/util/security/MD5Utils.java |
| | |
| | | com.demo.lib.common.okhttp.cookie.store.PersistentCookieStore |
| | | com/demo/lib/common/okhttp/builder/PostFileBuilder.java |
| | | com.demo.lib.common.okhttp.builder.PostFileBuilder |
| | | com/demo/lib/common/widget/RatioLayout.java |
| | | com.demo.lib.common.widget.RatioLayout |
| | | com/demo/lib/common/entity/ClipCopyContent.java |
| | | com.demo.lib.common.entity.ClipCopyContent |
| | | com/demo/lib/common/upgrade/UpdateActivity.java |
| | | com.demo.lib.common.upgrade.UpdateActivity |
| | | com.demo.lib.common.upgrade.UpdateActivity$1 |
| | | com.demo.lib.common.upgrade.UpdateActivity$2 |
| | | com/demo/lib/common/emotion/EmotionGridFragment.java |
| | | com.demo.lib.common.emotion.EmotionGridFragment |
| | | com.demo.lib.common.emotion.EmotionGridFragment$1 |
| | | com.demo.lib.common.emotion.EmotionGridFragment$EmotionAdapter |
| | | com.demo.lib.common.emotion.EmotionGridFragment$OnEditListener |
| | | com/demo/lib/common/util/PermissionsChecker.java |
| | | com.demo.lib.common.util.PermissionsChecker |
| | | com/demo/lib/common/DeviceUuidFactory.java |
| | | com.demo.lib.common.DeviceUuidFactory |
| | | com/demo/lib/common/widget/myswiperefreshlayout/MySwipeRefreshLayout.java |
| | |
| | | com/demo/lib/common/drawable/CrossFadeDrawable.java |
| | | com.demo.lib.common.drawable.CrossFadeDrawable |
| | | com.demo.lib.common.drawable.CrossFadeDrawable$1 |
| | | com/demo/lib/common/util/RefreshLayout.java |
| | | com.demo.lib.common.util.RefreshLayout |
| | | com.demo.lib.common.util.RefreshLayout$OnLoadListener |
| | | com/demo/lib/common/widget/MyViewPager.java |
| | | com.demo.lib.common.widget.MyViewPager |
| | | com/demo/lib/common/util/common/SerializeUtils.java |
| | | com.demo.lib.common.util.common.SerializeUtils |
| | | com/demo/lib/common/okhttp/callback/StringCallback.java |
| | |
| | | com.demo.lib.common.util.common.IClipboardContentListener |
| | | com/demo/lib/common/drawable/FastBitmapDrawable.java |
| | | com.demo.lib.common.drawable.FastBitmapDrawable |
| | | com/demo/lib/common/widget/AdaptiveListView.java |
| | | com.demo.lib.common.widget.AdaptiveListView |
| | | com/demo/lib/common/content/CursorLoader.java |
| | | com.demo.lib.common.content.CursorLoader |
| | | com/demo/lib/common/okhttp/utils/Platform.java |
| | | com.demo.lib.common.okhttp.utils.Platform |
| | | com.demo.lib.common.okhttp.utils.Platform$Android |
| | | com.demo.lib.common.okhttp.utils.Platform$Android$MainThreadExecutor |
| | | com/demo/lib/common/widget/MyViewPager.java |
| | | com.demo.lib.common.widget.MyViewPager |
| | | com/demo/lib/common/util/common/StringUtils.java |
| | | com.demo.lib.common.util.common.StringUtils |
| | | com/demo/lib/common/util/PermissionsChecker.java |
| | | com.demo.lib.common.util.PermissionsChecker |
| | | com/demo/lib/common/entity/ClipCopyContent.java |
| | | com.demo.lib.common.entity.ClipCopyContent |
| | | com/demo/lib/common/widget/MyGridView.java |
| | | com.demo.lib.common.widget.MyGridView |
| | | com/demo/lib/common/okhttp/request/PostStringRequest.java |
| | | com.demo.lib.common.okhttp.request.PostStringRequest |
| | | com/demo/lib/common/okhttp/request/PostFormRequest.java |
| | | com.demo.lib.common.okhttp.request.PostFormRequest |
| | | com.demo.lib.common.okhttp.request.PostFormRequest$1 |
| | | com.demo.lib.common.okhttp.request.PostFormRequest$1$1 |
| | | com/demo/lib/common/widget/TagCloudLayout.java |
| | | com.demo.lib.common.widget.TagCloudLayout |
| | | com.demo.lib.common.widget.TagCloudLayout$FlingRunnable |
| | | com.demo.lib.common.widget.TagCloudLayout$OnScrollListener |
| | | com.demo.lib.common.widget.TagCloudLayout$TagView |
| | | com/demo/lib/common/widget/verticalviewpager/ExtendedWebView.java |
| | | com.demo.lib.common.widget.verticalviewpager.ExtendedWebView |
| | | com/demo/lib/common/okhttp/utils/L.java |
| | | com.demo.lib.common.okhttp.utils.L |
| | | com/demo/lib/common/content/CursorLoader.java |
| | | com.demo.lib.common.content.CursorLoader |
| | | com/demo/lib/common/dialog/BottomDialog.java |
| | | com.demo.lib.common.dialog.BottomDialog |
| | | com/demo/lib/common/emotion/EmotionEditText.java |
| | | com.demo.lib.common.emotion.EmotionEditText |
| | | com/demo/lib/common/widget/FlowLayout.java |
| | | com.demo.lib.common.widget.FlowLayout |
| | | com/demo/lib/common/widget/ShelfView.java |
| | | com.demo.lib.common.widget.ShelfView |
| | | com/demo/lib/common/util/ui/LoadingDialogUtil.java |
| | | com.demo.lib.common.util.ui.LoadingDialogUtil |
| | | com/demo/lib/common/widget/AdaptiveListView.java |
| | | com.demo.lib.common.widget.AdaptiveListView |
| | | com/demo/lib/common/emotion/EmotionTextView.java |
| | | com.demo.lib.common.emotion.EmotionTextView |
| | | com/demo/lib/common/widget/RatioLayout.java |
| | | com.demo.lib.common.widget.RatioLayout |
| | | com/demo/lib/common/emotion/EmotionGridFragment.java |
| | | com.demo.lib.common.emotion.EmotionGridFragment |
| | | com.demo.lib.common.emotion.EmotionGridFragment$1 |
| | | com.demo.lib.common.emotion.EmotionGridFragment$EmotionAdapter |
| | | com.demo.lib.common.emotion.EmotionGridFragment$OnEditListener |
| | | com/demo/lib/common/drawable/SpotlightDrawable.java |
| | | com.demo.lib.common.drawable.SpotlightDrawable |
| | | com/demo/lib/common/util/RefreshLayout.java |
| | | com.demo.lib.common.util.RefreshLayout |
| | | com.demo.lib.common.util.RefreshLayout$OnLoadListener |
| | | com/demo/lib/common/dialog/SlidingDialog.java |
| | | com.demo.lib.common.dialog.SlidingDialog |
New file |
| | |
| | | # Miscellaneous |
| | | *.class |
| | | *.log |
| | | *.pyc |
| | | *.swp |
| | | .DS_Store |
| | | .atom/ |
| | | .buildlog/ |
| | | .history |
| | | .svn/ |
| | | |
| | | # IntelliJ related |
| | | *.iml |
| | | *.ipr |
| | | *.iws |
| | | .idea/ |
| | | |
| | | # The .vscode folder contains launch configuration and tasks you configure in |
| | | # VS Code which you may wish to be included in version control, so this line |
| | | # is commented out by default. |
| | | #.vscode/ |
| | | |
| | | # Flutter/Dart/Pub related |
| | | **/doc/api/ |
| | | **/ios/Flutter/.last_build_id |
| | | .dart_tool/ |
| | | .flutter-plugins |
| | | .flutter-plugins-dependencies |
| | | .packages |
| | | .pub-cache/ |
| | | .pub/ |
| | | /build/ |
| | | |
| | | # Web related |
| | | lib/generated_plugin_registrant.dart |
| | | |
| | | # Symbolication related |
| | | app.*.symbols |
| | | |
| | | # Obfuscation related |
| | | app.*.map.json |
| | | |
| | | # Android Studio will place build artifacts here |
| | | /android/app/debug |
| | | /android/app/profile |
| | | /android/app/release |
New file |
| | |
| | | # This file tracks properties of this Flutter project. |
| | | # Used by Flutter tool to assess capabilities and perform upgrades etc. |
| | | # |
| | | # This file should be version controlled and should not be manually edited. |
| | | |
| | | version: |
| | | revision: 18116933e77adc82f80866c928266a5b4f1ed645 |
| | | channel: stable |
| | | |
| | | project_type: app |
New file |
| | |
| | | # hanju |
| | | |
| | | A new Flutter project. |
| | | |
| | | ## Getting Started |
| | | |
| | | This project is a starting point for a Flutter application. |
| | | |
| | | A few resources to get you started if this is your first Flutter project: |
| | | |
| | | - [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) |
| | | - [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) |
| | | |
| | | For help getting started with Flutter, view our |
| | | [online documentation](https://flutter.dev/docs), which offers tutorials, |
| | | samples, guidance on mobile development, and a full API reference. |
New file |
| | |
| | | # This file configures the analyzer, which statically analyzes Dart code to |
| | | # check for errors, warnings, and lints. |
| | | # |
| | | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled |
| | | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be |
| | | # invoked from the command line by running `flutter analyze`. |
| | | |
| | | # The following line activates a set of recommended lints for Flutter apps, |
| | | # packages, and plugins designed to encourage good coding practices. |
| | | include: package:flutter_lints/flutter.yaml |
| | | |
| | | linter: |
| | | # The lint rules applied to this project can be customized in the |
| | | # section below to disable rules from the `package:flutter_lints/flutter.yaml` |
| | | # included above or to enable additional rules. A list of all available lints |
| | | # and their documentation is published at |
| | | # https://dart-lang.github.io/linter/lints/index.html. |
| | | # |
| | | # Instead of disabling a lint rule for the entire project in the |
| | | # section below, it can also be suppressed for a single line of code |
| | | # or a specific dart file by using the `// ignore: name_of_lint` and |
| | | # `// ignore_for_file: name_of_lint` syntax on the line or in the file |
| | | # producing the lint. |
| | | rules: |
| | | # avoid_print: false # Uncomment to disable the `avoid_print` rule |
| | | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule |
| | | |
| | | # Additional information about this file can be found at |
| | | # https://dart.dev/guides/language/analysis-options |
New file |
| | |
| | | gradle-wrapper.jar |
| | | /.gradle |
| | | /captures/ |
| | | /gradlew |
| | | /gradlew.bat |
| | | /local.properties |
| | | GeneratedPluginRegistrant.java |
| | | |
| | | # Remember to never publicly share your keystore. |
| | | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app |
| | | key.properties |
| | | **/*.keystore |
| | | **/*.jks |
New file |
| | |
| | | def localProperties = new Properties() |
| | | def localPropertiesFile = rootProject.file('local.properties') |
| | | if (localPropertiesFile.exists()) { |
| | | localPropertiesFile.withReader('UTF-8') { reader -> |
| | | localProperties.load(reader) |
| | | } |
| | | } |
| | | |
| | | def flutterRoot = localProperties.getProperty('flutter.sdk') |
| | | if (flutterRoot == null) { |
| | | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") |
| | | } |
| | | |
| | | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') |
| | | if (flutterVersionCode == null) { |
| | | flutterVersionCode = '1' |
| | | } |
| | | |
| | | def flutterVersionName = localProperties.getProperty('flutter.versionName') |
| | | if (flutterVersionName == null) { |
| | | flutterVersionName = '1.0' |
| | | } |
| | | |
| | | apply plugin: 'com.android.application' |
| | | apply plugin: 'kotlin-android' |
| | | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" |
| | | |
| | | android { |
| | | compileSdkVersion 30 |
| | | |
| | | compileOptions { |
| | | sourceCompatibility JavaVersion.VERSION_1_8 |
| | | targetCompatibility JavaVersion.VERSION_1_8 |
| | | } |
| | | |
| | | kotlinOptions { |
| | | jvmTarget = '1.8' |
| | | } |
| | | |
| | | sourceSets { |
| | | main.java.srcDirs += 'src/main/kotlin' |
| | | } |
| | | |
| | | defaultConfig { |
| | | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). |
| | | applicationId "com.example.hanju" |
| | | minSdkVersion 16 |
| | | targetSdkVersion 30 |
| | | versionCode flutterVersionCode.toInteger() |
| | | versionName flutterVersionName |
| | | } |
| | | |
| | | buildTypes { |
| | | release { |
| | | // TODO: Add your own signing config for the release build. |
| | | // Signing with the debug keys for now, so `flutter run --release` works. |
| | | signingConfig signingConfigs.debug |
| | | } |
| | | } |
| | | } |
| | | |
| | | flutter { |
| | | source '../..' |
| | | } |
| | | |
| | | dependencies { |
| | | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" |
| | | } |
New file |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| | | package="com.example.hanju"> |
| | | <!-- Flutter needs it to communicate with the running application |
| | | to allow setting breakpoints, to provide hot reload, etc. |
| | | --> |
| | | <uses-permission android:name="android.permission.INTERNET"/> |
| | | </manifest> |
New file |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| | | package="com.example.hanju"> |
| | | <application |
| | | android:label="hanju" |
| | | android:icon="@mipmap/ic_launcher"> |
| | | <activity |
| | | android:name=".MainActivity" |
| | | android:launchMode="singleTop" |
| | | android:theme="@style/LaunchTheme" |
| | | android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" |
| | | android:hardwareAccelerated="true" |
| | | android:windowSoftInputMode="adjustResize"> |
| | | <!-- Specifies an Android theme to apply to this Activity as soon as |
| | | the Android process has started. This theme is visible to the user |
| | | while the Flutter UI initializes. After that, this theme continues |
| | | to determine the Window background behind the Flutter UI. --> |
| | | <meta-data |
| | | android:name="io.flutter.embedding.android.NormalTheme" |
| | | android:resource="@style/NormalTheme" |
| | | /> |
| | | <!-- Displays an Android View that continues showing the launch screen |
| | | Drawable until Flutter paints its first frame, then this splash |
| | | screen fades out. A splash screen is useful to avoid any visual |
| | | gap between the end of Android's launch screen and the painting of |
| | | Flutter's first frame. --> |
| | | <meta-data |
| | | android:name="io.flutter.embedding.android.SplashScreenDrawable" |
| | | android:resource="@drawable/launch_background" |
| | | /> |
| | | <intent-filter> |
| | | <action android:name="android.intent.action.MAIN"/> |
| | | <category android:name="android.intent.category.LAUNCHER"/> |
| | | </intent-filter> |
| | | </activity> |
| | | <!-- Don't delete the meta-data below. |
| | | This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> |
| | | <meta-data |
| | | android:name="flutterEmbedding" |
| | | android:value="2" /> |
| | | </application> |
| | | </manifest> |
New file |
| | |
| | | package com.example.hanju |
| | | |
| | | import io.flutter.embedding.android.FlutterActivity |
| | | |
| | | class MainActivity: FlutterActivity() { |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <!-- Modify this file to customize your launch splash screen --> |
| | | <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <item android:drawable="?android:colorBackground" /> |
| | | |
| | | <!-- You can insert your own image assets here --> |
| | | <!-- <item> |
| | | <bitmap |
| | | android:gravity="center" |
| | | android:src="@mipmap/launch_image" /> |
| | | </item> --> |
| | | </layer-list> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <!-- Modify this file to customize your launch splash screen --> |
| | | <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> |
| | | <item android:drawable="@android:color/white" /> |
| | | |
| | | <!-- You can insert your own image assets here --> |
| | | <!-- <item> |
| | | <bitmap |
| | | android:gravity="center" |
| | | android:src="@mipmap/launch_image" /> |
| | | </item> --> |
| | | </layer-list> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> |
| | | <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
| | | <!-- Show a splash screen on the activity. Automatically removed when |
| | | Flutter draws its first frame --> |
| | | <item name="android:windowBackground">@drawable/launch_background</item> |
| | | </style> |
| | | <!-- Theme applied to the Android Window as soon as the process has started. |
| | | This theme determines the color of the Android Window while your |
| | | Flutter UI initializes, as well as behind your Flutter UI while its |
| | | running. |
| | | |
| | | This Theme is only used starting with V2 of Flutter's Android embedding. --> |
| | | <style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar"> |
| | | <item name="android:windowBackground">?android:colorBackground</item> |
| | | </style> |
| | | </resources> |
New file |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <resources> |
| | | <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> |
| | | <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
| | | <!-- Show a splash screen on the activity. Automatically removed when |
| | | Flutter draws its first frame --> |
| | | <item name="android:windowBackground">@drawable/launch_background</item> |
| | | </style> |
| | | <!-- Theme applied to the Android Window as soon as the process has started. |
| | | This theme determines the color of the Android Window while your |
| | | Flutter UI initializes, as well as behind your Flutter UI while its |
| | | running. |
| | | |
| | | This Theme is only used starting with V2 of Flutter's Android embedding. --> |
| | | <style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar"> |
| | | <item name="android:windowBackground">?android:colorBackground</item> |
| | | </style> |
| | | </resources> |
New file |
| | |
| | | <manifest xmlns:android="http://schemas.android.com/apk/res/android" |
| | | package="com.example.hanju"> |
| | | <!-- Flutter needs it to communicate with the running application |
| | | to allow setting breakpoints, to provide hot reload, etc. |
| | | --> |
| | | <uses-permission android:name="android.permission.INTERNET"/> |
| | | </manifest> |
New file |
| | |
| | | buildscript { |
| | | ext.kotlin_version = '1.3.50' |
| | | repositories { |
| | | google() |
| | | mavenCentral() |
| | | } |
| | | |
| | | dependencies { |
| | | classpath 'com.android.tools.build:gradle:4.1.0' |
| | | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| | | } |
| | | } |
| | | |
| | | allprojects { |
| | | repositories { |
| | | google() |
| | | mavenCentral() |
| | | } |
| | | } |
| | | |
| | | rootProject.buildDir = '../build' |
| | | subprojects { |
| | | project.buildDir = "${rootProject.buildDir}/${project.name}" |
| | | project.evaluationDependsOn(':app') |
| | | } |
| | | |
| | | task clean(type: Delete) { |
| | | delete rootProject.buildDir |
| | | } |
New file |
| | |
| | | org.gradle.jvmargs=-Xmx1536M |
| | | android.useAndroidX=true |
| | | android.enableJetifier=true |
New file |
| | |
| | | #Fri Jun 23 08:50:38 CEST 2017 |
| | | distributionBase=GRADLE_USER_HOME |
| | | distributionPath=wrapper/dists |
| | | zipStoreBase=GRADLE_USER_HOME |
| | | zipStorePath=wrapper/dists |
| | | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip |
New file |
| | |
| | | include ':app' |
| | | |
| | | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") |
| | | def properties = new Properties() |
| | | |
| | | assert localPropertiesFile.exists() |
| | | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } |
| | | |
| | | def flutterSdkPath = properties.getProperty("flutter.sdk") |
| | | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" |
| | | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" |
New file |
| | |
| | | **/dgph |
| | | *.mode1v3 |
| | | *.mode2v3 |
| | | *.moved-aside |
| | | *.pbxuser |
| | | *.perspectivev3 |
| | | **/*sync/ |
| | | .sconsign.dblite |
| | | .tags* |
| | | **/.vagrant/ |
| | | **/DerivedData/ |
| | | Icon? |
| | | **/Pods/ |
| | | **/.symlinks/ |
| | | profile |
| | | xcuserdata |
| | | **/.generated/ |
| | | Flutter/App.framework |
| | | Flutter/Flutter.framework |
| | | Flutter/Flutter.podspec |
| | | Flutter/Generated.xcconfig |
| | | Flutter/ephemeral/ |
| | | Flutter/app.flx |
| | | Flutter/app.zip |
| | | Flutter/flutter_assets/ |
| | | Flutter/flutter_export_environment.sh |
| | | ServiceDefinitions.json |
| | | Runner/GeneratedPluginRegistrant.* |
| | | |
| | | # Exceptions to above rules. |
| | | !default.mode1v3 |
| | | !default.mode2v3 |
| | | !default.pbxuser |
| | | !default.perspectivev3 |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>CFBundleDevelopmentRegion</key> |
| | | <string>en</string> |
| | | <key>CFBundleExecutable</key> |
| | | <string>App</string> |
| | | <key>CFBundleIdentifier</key> |
| | | <string>io.flutter.flutter.app</string> |
| | | <key>CFBundleInfoDictionaryVersion</key> |
| | | <string>6.0</string> |
| | | <key>CFBundleName</key> |
| | | <string>App</string> |
| | | <key>CFBundlePackageType</key> |
| | | <string>FMWK</string> |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>1.0</string> |
| | | <key>CFBundleSignature</key> |
| | | <string>????</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>1.0</string> |
| | | <key>MinimumOSVersion</key> |
| | | <string>9.0</string> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | #include "Generated.xcconfig" |
New file |
| | |
| | | #include "Generated.xcconfig" |
New file |
| | |
| | | // !$*UTF8*$! |
| | | { |
| | | archiveVersion = 1; |
| | | classes = { |
| | | }; |
| | | objectVersion = 50; |
| | | objects = { |
| | | |
| | | /* Begin PBXBuildFile section */ |
| | | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; |
| | | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; |
| | | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; |
| | | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; |
| | | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; |
| | | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; |
| | | /* End PBXBuildFile section */ |
| | | |
| | | /* Begin PBXCopyFilesBuildPhase section */ |
| | | 9705A1C41CF9048500538489 /* Embed Frameworks */ = { |
| | | isa = PBXCopyFilesBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | dstPath = ""; |
| | | dstSubfolderSpec = 10; |
| | | files = ( |
| | | ); |
| | | name = "Embed Frameworks"; |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXCopyFilesBuildPhase section */ |
| | | |
| | | /* Begin PBXFileReference section */ |
| | | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; |
| | | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; |
| | | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; |
| | | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; |
| | | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; |
| | | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; |
| | | 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; |
| | | 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; |
| | | 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
| | | 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; |
| | | 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; |
| | | 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; |
| | | 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; |
| | | /* End PBXFileReference section */ |
| | | |
| | | /* Begin PBXFrameworksBuildPhase section */ |
| | | 97C146EB1CF9000F007C117D /* Frameworks */ = { |
| | | isa = PBXFrameworksBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXFrameworksBuildPhase section */ |
| | | |
| | | /* Begin PBXGroup section */ |
| | | 9740EEB11CF90186004384FC /* Flutter */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, |
| | | 9740EEB21CF90195004384FC /* Debug.xcconfig */, |
| | | 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, |
| | | 9740EEB31CF90195004384FC /* Generated.xcconfig */, |
| | | ); |
| | | name = Flutter; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 97C146E51CF9000F007C117D = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 9740EEB11CF90186004384FC /* Flutter */, |
| | | 97C146F01CF9000F007C117D /* Runner */, |
| | | 97C146EF1CF9000F007C117D /* Products */, |
| | | ); |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 97C146EF1CF9000F007C117D /* Products */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 97C146EE1CF9000F007C117D /* Runner.app */, |
| | | ); |
| | | name = Products; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 97C146F01CF9000F007C117D /* Runner */ = { |
| | | isa = PBXGroup; |
| | | children = ( |
| | | 97C146FA1CF9000F007C117D /* Main.storyboard */, |
| | | 97C146FD1CF9000F007C117D /* Assets.xcassets */, |
| | | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, |
| | | 97C147021CF9000F007C117D /* Info.plist */, |
| | | 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, |
| | | 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, |
| | | 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, |
| | | 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, |
| | | ); |
| | | path = Runner; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | /* End PBXGroup section */ |
| | | |
| | | /* Begin PBXNativeTarget section */ |
| | | 97C146ED1CF9000F007C117D /* Runner */ = { |
| | | isa = PBXNativeTarget; |
| | | buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; |
| | | buildPhases = ( |
| | | 9740EEB61CF901F6004384FC /* Run Script */, |
| | | 97C146EA1CF9000F007C117D /* Sources */, |
| | | 97C146EB1CF9000F007C117D /* Frameworks */, |
| | | 97C146EC1CF9000F007C117D /* Resources */, |
| | | 9705A1C41CF9048500538489 /* Embed Frameworks */, |
| | | 3B06AD1E1E4923F5004D2608 /* Thin Binary */, |
| | | ); |
| | | buildRules = ( |
| | | ); |
| | | dependencies = ( |
| | | ); |
| | | name = Runner; |
| | | productName = Runner; |
| | | productReference = 97C146EE1CF9000F007C117D /* Runner.app */; |
| | | productType = "com.apple.product-type.application"; |
| | | }; |
| | | /* End PBXNativeTarget section */ |
| | | |
| | | /* Begin PBXProject section */ |
| | | 97C146E61CF9000F007C117D /* Project object */ = { |
| | | isa = PBXProject; |
| | | attributes = { |
| | | LastUpgradeCheck = 1020; |
| | | ORGANIZATIONNAME = ""; |
| | | TargetAttributes = { |
| | | 97C146ED1CF9000F007C117D = { |
| | | CreatedOnToolsVersion = 7.3.1; |
| | | LastSwiftMigration = 1100; |
| | | }; |
| | | }; |
| | | }; |
| | | buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; |
| | | compatibilityVersion = "Xcode 9.3"; |
| | | developmentRegion = en; |
| | | hasScannedForEncodings = 0; |
| | | knownRegions = ( |
| | | en, |
| | | Base, |
| | | ); |
| | | mainGroup = 97C146E51CF9000F007C117D; |
| | | productRefGroup = 97C146EF1CF9000F007C117D /* Products */; |
| | | projectDirPath = ""; |
| | | projectRoot = ""; |
| | | targets = ( |
| | | 97C146ED1CF9000F007C117D /* Runner */, |
| | | ); |
| | | }; |
| | | /* End PBXProject section */ |
| | | |
| | | /* Begin PBXResourcesBuildPhase section */ |
| | | 97C146EC1CF9000F007C117D /* Resources */ = { |
| | | isa = PBXResourcesBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, |
| | | 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, |
| | | 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, |
| | | 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXResourcesBuildPhase section */ |
| | | |
| | | /* Begin PBXShellScriptBuildPhase section */ |
| | | 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { |
| | | isa = PBXShellScriptBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | ); |
| | | inputPaths = ( |
| | | ); |
| | | name = "Thin Binary"; |
| | | outputPaths = ( |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | shellPath = /bin/sh; |
| | | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; |
| | | }; |
| | | 9740EEB61CF901F6004384FC /* Run Script */ = { |
| | | isa = PBXShellScriptBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | ); |
| | | inputPaths = ( |
| | | ); |
| | | name = "Run Script"; |
| | | outputPaths = ( |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | shellPath = /bin/sh; |
| | | shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; |
| | | }; |
| | | /* End PBXShellScriptBuildPhase section */ |
| | | |
| | | /* Begin PBXSourcesBuildPhase section */ |
| | | 97C146EA1CF9000F007C117D /* Sources */ = { |
| | | isa = PBXSourcesBuildPhase; |
| | | buildActionMask = 2147483647; |
| | | files = ( |
| | | 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, |
| | | 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, |
| | | ); |
| | | runOnlyForDeploymentPostprocessing = 0; |
| | | }; |
| | | /* End PBXSourcesBuildPhase section */ |
| | | |
| | | /* Begin PBXVariantGroup section */ |
| | | 97C146FA1CF9000F007C117D /* Main.storyboard */ = { |
| | | isa = PBXVariantGroup; |
| | | children = ( |
| | | 97C146FB1CF9000F007C117D /* Base */, |
| | | ); |
| | | name = Main.storyboard; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { |
| | | isa = PBXVariantGroup; |
| | | children = ( |
| | | 97C147001CF9000F007C117D /* Base */, |
| | | ); |
| | | name = LaunchScreen.storyboard; |
| | | sourceTree = "<group>"; |
| | | }; |
| | | /* End PBXVariantGroup section */ |
| | | |
| | | /* Begin XCBuildConfiguration section */ |
| | | 249021D3217E4FDB00AE95B9 /* Profile */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ALWAYS_SEARCH_USER_PATHS = NO; |
| | | CLANG_ANALYZER_NONNULL = YES; |
| | | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
| | | CLANG_CXX_LIBRARY = "libc++"; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CLANG_ENABLE_OBJC_ARC = YES; |
| | | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
| | | CLANG_WARN_BOOL_CONVERSION = YES; |
| | | CLANG_WARN_COMMA = YES; |
| | | CLANG_WARN_CONSTANT_CONVERSION = YES; |
| | | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
| | | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
| | | CLANG_WARN_EMPTY_BODY = YES; |
| | | CLANG_WARN_ENUM_CONVERSION = YES; |
| | | CLANG_WARN_INFINITE_RECURSION = YES; |
| | | CLANG_WARN_INT_CONVERSION = YES; |
| | | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; |
| | | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
| | | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
| | | CLANG_WARN_STRICT_PROTOTYPES = YES; |
| | | CLANG_WARN_SUSPICIOUS_MOVE = YES; |
| | | CLANG_WARN_UNREACHABLE_CODE = YES; |
| | | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | COPY_PHASE_STRIP = NO; |
| | | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
| | | ENABLE_NS_ASSERTIONS = NO; |
| | | ENABLE_STRICT_OBJC_MSGSEND = YES; |
| | | GCC_C_LANGUAGE_STANDARD = gnu99; |
| | | GCC_NO_COMMON_BLOCKS = YES; |
| | | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
| | | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
| | | GCC_WARN_UNDECLARED_SELECTOR = YES; |
| | | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| | | GCC_WARN_UNUSED_FUNCTION = YES; |
| | | GCC_WARN_UNUSED_VARIABLE = YES; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 9.0; |
| | | MTL_ENABLE_DEBUG_INFO = NO; |
| | | SDKROOT = iphoneos; |
| | | SUPPORTED_PLATFORMS = iphoneos; |
| | | TARGETED_DEVICE_FAMILY = "1,2"; |
| | | VALIDATE_PRODUCT = YES; |
| | | }; |
| | | name = Profile; |
| | | }; |
| | | 249021D4217E4FDB00AE95B9 /* Profile */ = { |
| | | isa = XCBuildConfiguration; |
| | | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; |
| | | buildSettings = { |
| | | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| | | DEVELOPMENT_TEAM = 98HSDT7AP4; |
| | | ENABLE_BITCODE = NO; |
| | | INFOPLIST_FILE = Runner/Info.plist; |
| | | LD_RUNPATH_SEARCH_PATHS = ( |
| | | "$(inherited)", |
| | | "@executable_path/Frameworks", |
| | | ); |
| | | PRODUCT_BUNDLE_IDENTIFIER = com.flutter.test; |
| | | PRODUCT_NAME = "$(TARGET_NAME)"; |
| | | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| | | SWIFT_VERSION = 5.0; |
| | | VERSIONING_SYSTEM = "apple-generic"; |
| | | }; |
| | | name = Profile; |
| | | }; |
| | | 97C147031CF9000F007C117D /* Debug */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ALWAYS_SEARCH_USER_PATHS = NO; |
| | | CLANG_ANALYZER_NONNULL = YES; |
| | | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
| | | CLANG_CXX_LIBRARY = "libc++"; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CLANG_ENABLE_OBJC_ARC = YES; |
| | | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
| | | CLANG_WARN_BOOL_CONVERSION = YES; |
| | | CLANG_WARN_COMMA = YES; |
| | | CLANG_WARN_CONSTANT_CONVERSION = YES; |
| | | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
| | | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
| | | CLANG_WARN_EMPTY_BODY = YES; |
| | | CLANG_WARN_ENUM_CONVERSION = YES; |
| | | CLANG_WARN_INFINITE_RECURSION = YES; |
| | | CLANG_WARN_INT_CONVERSION = YES; |
| | | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; |
| | | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
| | | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
| | | CLANG_WARN_STRICT_PROTOTYPES = YES; |
| | | CLANG_WARN_SUSPICIOUS_MOVE = YES; |
| | | CLANG_WARN_UNREACHABLE_CODE = YES; |
| | | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | COPY_PHASE_STRIP = NO; |
| | | DEBUG_INFORMATION_FORMAT = dwarf; |
| | | ENABLE_STRICT_OBJC_MSGSEND = YES; |
| | | ENABLE_TESTABILITY = YES; |
| | | GCC_C_LANGUAGE_STANDARD = gnu99; |
| | | GCC_DYNAMIC_NO_PIC = NO; |
| | | GCC_NO_COMMON_BLOCKS = YES; |
| | | GCC_OPTIMIZATION_LEVEL = 0; |
| | | GCC_PREPROCESSOR_DEFINITIONS = ( |
| | | "DEBUG=1", |
| | | "$(inherited)", |
| | | ); |
| | | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
| | | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
| | | GCC_WARN_UNDECLARED_SELECTOR = YES; |
| | | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| | | GCC_WARN_UNUSED_FUNCTION = YES; |
| | | GCC_WARN_UNUSED_VARIABLE = YES; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 9.0; |
| | | MTL_ENABLE_DEBUG_INFO = YES; |
| | | ONLY_ACTIVE_ARCH = YES; |
| | | SDKROOT = iphoneos; |
| | | TARGETED_DEVICE_FAMILY = "1,2"; |
| | | }; |
| | | name = Debug; |
| | | }; |
| | | 97C147041CF9000F007C117D /* Release */ = { |
| | | isa = XCBuildConfiguration; |
| | | buildSettings = { |
| | | ALWAYS_SEARCH_USER_PATHS = NO; |
| | | CLANG_ANALYZER_NONNULL = YES; |
| | | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; |
| | | CLANG_CXX_LIBRARY = "libc++"; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CLANG_ENABLE_OBJC_ARC = YES; |
| | | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; |
| | | CLANG_WARN_BOOL_CONVERSION = YES; |
| | | CLANG_WARN_COMMA = YES; |
| | | CLANG_WARN_CONSTANT_CONVERSION = YES; |
| | | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; |
| | | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; |
| | | CLANG_WARN_EMPTY_BODY = YES; |
| | | CLANG_WARN_ENUM_CONVERSION = YES; |
| | | CLANG_WARN_INFINITE_RECURSION = YES; |
| | | CLANG_WARN_INT_CONVERSION = YES; |
| | | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; |
| | | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; |
| | | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; |
| | | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; |
| | | CLANG_WARN_STRICT_PROTOTYPES = YES; |
| | | CLANG_WARN_SUSPICIOUS_MOVE = YES; |
| | | CLANG_WARN_UNREACHABLE_CODE = YES; |
| | | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; |
| | | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; |
| | | COPY_PHASE_STRIP = NO; |
| | | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; |
| | | ENABLE_NS_ASSERTIONS = NO; |
| | | ENABLE_STRICT_OBJC_MSGSEND = YES; |
| | | GCC_C_LANGUAGE_STANDARD = gnu99; |
| | | GCC_NO_COMMON_BLOCKS = YES; |
| | | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; |
| | | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; |
| | | GCC_WARN_UNDECLARED_SELECTOR = YES; |
| | | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; |
| | | GCC_WARN_UNUSED_FUNCTION = YES; |
| | | GCC_WARN_UNUSED_VARIABLE = YES; |
| | | IPHONEOS_DEPLOYMENT_TARGET = 9.0; |
| | | MTL_ENABLE_DEBUG_INFO = NO; |
| | | SDKROOT = iphoneos; |
| | | SUPPORTED_PLATFORMS = iphoneos; |
| | | SWIFT_COMPILATION_MODE = wholemodule; |
| | | SWIFT_OPTIMIZATION_LEVEL = "-O"; |
| | | TARGETED_DEVICE_FAMILY = "1,2"; |
| | | VALIDATE_PRODUCT = YES; |
| | | }; |
| | | name = Release; |
| | | }; |
| | | 97C147061CF9000F007C117D /* Debug */ = { |
| | | isa = XCBuildConfiguration; |
| | | baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; |
| | | buildSettings = { |
| | | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| | | DEVELOPMENT_TEAM = 98HSDT7AP4; |
| | | ENABLE_BITCODE = NO; |
| | | INFOPLIST_FILE = Runner/Info.plist; |
| | | LD_RUNPATH_SEARCH_PATHS = ( |
| | | "$(inherited)", |
| | | "@executable_path/Frameworks", |
| | | ); |
| | | PRODUCT_BUNDLE_IDENTIFIER = com.flutter.test; |
| | | PRODUCT_NAME = "$(TARGET_NAME)"; |
| | | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| | | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; |
| | | SWIFT_VERSION = 5.0; |
| | | VERSIONING_SYSTEM = "apple-generic"; |
| | | }; |
| | | name = Debug; |
| | | }; |
| | | 97C147071CF9000F007C117D /* Release */ = { |
| | | isa = XCBuildConfiguration; |
| | | baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; |
| | | buildSettings = { |
| | | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; |
| | | CLANG_ENABLE_MODULES = YES; |
| | | CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; |
| | | DEVELOPMENT_TEAM = 98HSDT7AP4; |
| | | ENABLE_BITCODE = NO; |
| | | INFOPLIST_FILE = Runner/Info.plist; |
| | | LD_RUNPATH_SEARCH_PATHS = ( |
| | | "$(inherited)", |
| | | "@executable_path/Frameworks", |
| | | ); |
| | | PRODUCT_BUNDLE_IDENTIFIER = com.flutter.test; |
| | | PRODUCT_NAME = "$(TARGET_NAME)"; |
| | | SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; |
| | | SWIFT_VERSION = 5.0; |
| | | VERSIONING_SYSTEM = "apple-generic"; |
| | | }; |
| | | name = Release; |
| | | }; |
| | | /* End XCBuildConfiguration section */ |
| | | |
| | | /* Begin XCConfigurationList section */ |
| | | 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { |
| | | isa = XCConfigurationList; |
| | | buildConfigurations = ( |
| | | 97C147031CF9000F007C117D /* Debug */, |
| | | 97C147041CF9000F007C117D /* Release */, |
| | | 249021D3217E4FDB00AE95B9 /* Profile */, |
| | | ); |
| | | defaultConfigurationIsVisible = 0; |
| | | defaultConfigurationName = Release; |
| | | }; |
| | | 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { |
| | | isa = XCConfigurationList; |
| | | buildConfigurations = ( |
| | | 97C147061CF9000F007C117D /* Debug */, |
| | | 97C147071CF9000F007C117D /* Release */, |
| | | 249021D4217E4FDB00AE95B9 /* Profile */, |
| | | ); |
| | | defaultConfigurationIsVisible = 0; |
| | | defaultConfigurationName = Release; |
| | | }; |
| | | /* End XCConfigurationList section */ |
| | | }; |
| | | rootObject = 97C146E61CF9000F007C117D /* Project object */; |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Workspace |
| | | version = "1.0"> |
| | | <FileRef |
| | | location = "self:"> |
| | | </FileRef> |
| | | </Workspace> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>IDEDidComputeMac32BitWarning</key> |
| | | <true/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>PreviewsEnabled</key> |
| | | <false/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Scheme |
| | | LastUpgradeVersion = "1020" |
| | | version = "1.3"> |
| | | <BuildAction |
| | | parallelizeBuildables = "YES" |
| | | buildImplicitDependencies = "YES"> |
| | | <BuildActionEntries> |
| | | <BuildActionEntry |
| | | buildForTesting = "YES" |
| | | buildForRunning = "YES" |
| | | buildForProfiling = "YES" |
| | | buildForArchiving = "YES" |
| | | buildForAnalyzing = "YES"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
| | | BuildableName = "Runner.app" |
| | | BlueprintName = "Runner" |
| | | ReferencedContainer = "container:Runner.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildActionEntry> |
| | | </BuildActionEntries> |
| | | </BuildAction> |
| | | <TestAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | shouldUseLaunchSchemeArgsEnv = "YES"> |
| | | <Testables> |
| | | </Testables> |
| | | <MacroExpansion> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
| | | BuildableName = "Runner.app" |
| | | BlueprintName = "Runner" |
| | | ReferencedContainer = "container:Runner.xcodeproj"> |
| | | </BuildableReference> |
| | | </MacroExpansion> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </TestAction> |
| | | <LaunchAction |
| | | buildConfiguration = "Debug" |
| | | selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
| | | selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
| | | launchStyle = "0" |
| | | useCustomWorkingDirectory = "NO" |
| | | ignoresPersistentStateOnLaunch = "NO" |
| | | debugDocumentVersioning = "YES" |
| | | debugServiceExtension = "internal" |
| | | allowLocationSimulation = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
| | | BuildableName = "Runner.app" |
| | | BlueprintName = "Runner" |
| | | ReferencedContainer = "container:Runner.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | <AdditionalOptions> |
| | | </AdditionalOptions> |
| | | </LaunchAction> |
| | | <ProfileAction |
| | | buildConfiguration = "Profile" |
| | | shouldUseLaunchSchemeArgsEnv = "YES" |
| | | savedToolIdentifier = "" |
| | | useCustomWorkingDirectory = "NO" |
| | | debugDocumentVersioning = "YES"> |
| | | <BuildableProductRunnable |
| | | runnableDebuggingMode = "0"> |
| | | <BuildableReference |
| | | BuildableIdentifier = "primary" |
| | | BlueprintIdentifier = "97C146ED1CF9000F007C117D" |
| | | BuildableName = "Runner.app" |
| | | BlueprintName = "Runner" |
| | | ReferencedContainer = "container:Runner.xcodeproj"> |
| | | </BuildableReference> |
| | | </BuildableProductRunnable> |
| | | </ProfileAction> |
| | | <AnalyzeAction |
| | | buildConfiguration = "Debug"> |
| | | </AnalyzeAction> |
| | | <ArchiveAction |
| | | buildConfiguration = "Release" |
| | | revealArchiveInOrganizer = "YES"> |
| | | </ArchiveAction> |
| | | </Scheme> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <Workspace |
| | | version = "1.0"> |
| | | <FileRef |
| | | location = "group:Runner.xcodeproj"> |
| | | </FileRef> |
| | | </Workspace> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>IDEDidComputeMac32BitWarning</key> |
| | | <true/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>PreviewsEnabled</key> |
| | | <false/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | import UIKit |
| | | import Flutter |
| | | |
| | | @UIApplicationMain |
| | | @objc class AppDelegate: FlutterAppDelegate { |
| | | override func application( |
| | | _ application: UIApplication, |
| | | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? |
| | | ) -> Bool { |
| | | GeneratedPluginRegistrant.register(with: self) |
| | | return super.application(application, didFinishLaunchingWithOptions: launchOptions) |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-20x20@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-20x20@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-29x29@1x.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-29x29@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-29x29@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-40x40@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-40x40@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "60x60", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-60x60@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "60x60", |
| | | "idiom" : "iphone", |
| | | "filename" : "Icon-App-60x60@3x.png", |
| | | "scale" : "3x" |
| | | }, |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-20x20@1x.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "20x20", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-20x20@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-29x29@1x.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "29x29", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-29x29@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-40x40@1x.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "40x40", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-40x40@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "76x76", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-76x76@1x.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "size" : "76x76", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-76x76@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "83.5x83.5", |
| | | "idiom" : "ipad", |
| | | "filename" : "Icon-App-83.5x83.5@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "size" : "1024x1024", |
| | | "idiom" : "ios-marketing", |
| | | "filename" : "Icon-App-1024x1024@1x.png", |
| | | "scale" : "1x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | { |
| | | "images" : [ |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "LaunchImage.png", |
| | | "scale" : "1x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "LaunchImage@2x.png", |
| | | "scale" : "2x" |
| | | }, |
| | | { |
| | | "idiom" : "universal", |
| | | "filename" : "LaunchImage@3x.png", |
| | | "scale" : "3x" |
| | | } |
| | | ], |
| | | "info" : { |
| | | "version" : 1, |
| | | "author" : "xcode" |
| | | } |
| | | } |
New file |
| | |
| | | # Launch Screen Assets |
| | | |
| | | You can customize the launch screen with your own desired assets by replacing the image files in this directory. |
| | | |
| | | 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. |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" standalone="no"?> |
| | | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM"> |
| | | <dependencies> |
| | | <deployment identifier="iOS"/> |
| | | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/> |
| | | </dependencies> |
| | | <scenes> |
| | | <!--View Controller--> |
| | | <scene sceneID="EHf-IW-A2E"> |
| | | <objects> |
| | | <viewController id="01J-lp-oVM" sceneMemberID="viewController"> |
| | | <layoutGuides> |
| | | <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/> |
| | | <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/> |
| | | </layoutGuides> |
| | | <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> |
| | | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| | | <subviews> |
| | | <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> |
| | | </imageView> |
| | | </subviews> |
| | | <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| | | <constraints> |
| | | <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> |
| | | <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/> |
| | | </constraints> |
| | | </view> |
| | | </viewController> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/> |
| | | </objects> |
| | | <point key="canvasLocation" x="53" y="375"/> |
| | | </scene> |
| | | </scenes> |
| | | <resources> |
| | | <image name="LaunchImage" width="168" height="185"/> |
| | | </resources> |
| | | </document> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8" standalone="no"?> |
| | | <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r"> |
| | | <dependencies> |
| | | <deployment identifier="iOS"/> |
| | | <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/> |
| | | </dependencies> |
| | | <scenes> |
| | | <!--Flutter View Controller--> |
| | | <scene sceneID="tne-QT-ifu"> |
| | | <objects> |
| | | <viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController"> |
| | | <layoutGuides> |
| | | <viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/> |
| | | <viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/> |
| | | </layoutGuides> |
| | | <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> |
| | | <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> |
| | | <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| | | <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/> |
| | | </view> |
| | | </viewController> |
| | | <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> |
| | | </objects> |
| | | </scene> |
| | | </scenes> |
| | | </document> |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
| | | <plist version="1.0"> |
| | | <dict> |
| | | <key>CFBundleDevelopmentRegion</key> |
| | | <string>$(DEVELOPMENT_LANGUAGE)</string> |
| | | <key>CFBundleExecutable</key> |
| | | <string>$(EXECUTABLE_NAME)</string> |
| | | <key>CFBundleIdentifier</key> |
| | | <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> |
| | | <key>CFBundleInfoDictionaryVersion</key> |
| | | <string>6.0</string> |
| | | <key>CFBundleName</key> |
| | | <string>hanju</string> |
| | | <key>CFBundlePackageType</key> |
| | | <string>APPL</string> |
| | | <key>CFBundleShortVersionString</key> |
| | | <string>$(FLUTTER_BUILD_NAME)</string> |
| | | <key>CFBundleSignature</key> |
| | | <string>????</string> |
| | | <key>CFBundleVersion</key> |
| | | <string>$(FLUTTER_BUILD_NUMBER)</string> |
| | | <key>LSRequiresIPhoneOS</key> |
| | | <true/> |
| | | <key>UILaunchStoryboardName</key> |
| | | <string>LaunchScreen</string> |
| | | <key>UIMainStoryboardFile</key> |
| | | <string>Main</string> |
| | | <key>UISupportedInterfaceOrientations</key> |
| | | <array> |
| | | <string>UIInterfaceOrientationPortrait</string> |
| | | <string>UIInterfaceOrientationLandscapeLeft</string> |
| | | <string>UIInterfaceOrientationLandscapeRight</string> |
| | | </array> |
| | | <key>UISupportedInterfaceOrientations~ipad</key> |
| | | <array> |
| | | <string>UIInterfaceOrientationPortrait</string> |
| | | <string>UIInterfaceOrientationPortraitUpsideDown</string> |
| | | <string>UIInterfaceOrientationLandscapeLeft</string> |
| | | <string>UIInterfaceOrientationLandscapeRight</string> |
| | | </array> |
| | | <key>UIViewControllerBasedStatusBarAppearance</key> |
| | | <false/> |
| | | </dict> |
| | | </plist> |
New file |
| | |
| | | #import "GeneratedPluginRegistrant.h" |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | |
| | | import 'package:device_info/device_info.dart'; |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | import '../utils/string_util.dart'; |
| | | import '../utils/user_util.dart'; |
| | | import '../utils/app_util.dart'; |
| | | import '../utils/global.dart'; |
| | | import '../utils/encrypt_util.dart'; |
| | | import '../ui/widget/dialog.dart'; |
| | | import '../utils/ui_utils.dart'; |
| | | import '../model/common/http_model.dart'; |
| | | |
| | | typedef OnHttpRequestFinish = void Function(HttpRequestResult result); |
| | | |
| | | typedef OnHttpRequestStart = void Function(); |
| | | |
| | | showLoading(BuildContext context) { |
| | | //先丢失焦点 |
| | | FocusScope.of(context).unfocus(); |
| | | //开启加载框 |
| | | DialogUtil.showDialog(context, LoadingDialog("")); |
| | | } |
| | | |
| | | dismissDialog(BuildContext context) { |
| | | Navigator.pop(context); |
| | | } |
| | | |
| | | class HttpUtil { |
| | | static AndroidDeviceInfo? _androidInfo; |
| | | static IosDeviceInfo? _iosInfo; |
| | | |
| | | static _getSign(Map<String, dynamic> params) { |
| | | List list = []; |
| | | //签名 |
| | | params.forEach((key, value) { |
| | | list.add("$key=$value"); |
| | | }); |
| | | //排序 |
| | | list.sort(); |
| | | String signStr = ""; |
| | | list.forEach((element) { |
| | | signStr += element + "&"; |
| | | }); |
| | | |
| | | signStr += "@#\$^234AB&c&fg&.==888"; |
| | | |
| | | return EncryptUtil.MD5(signStr); |
| | | } |
| | | |
| | | static Future<Map<String, dynamic>> getBaseParams( |
| | | Map<String, dynamic>? params) async { |
| | | params ??= {}; |
| | | |
| | | if (Platform.isAndroid) { |
| | | if (_androidInfo == null) { |
| | | DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); |
| | | _androidInfo = await deviceInfo.androidInfo; |
| | | } |
| | | } else if (Platform.isIOS) { |
| | | if (_iosInfo == null) { |
| | | DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); |
| | | _iosInfo = await deviceInfo.iosInfo; |
| | | } |
| | | } |
| | | |
| | | params["version"] = (await AppUtil.getVersionCode()).toString(); |
| | | |
| | | print("androidInfo:${_androidInfo!.version}"); |
| | | |
| | | //添加附加参数 |
| | | params["timestamp"] = DateTime.now().millisecondsSinceEpoch.toString(); |
| | | params["platform"] = Platform.isAndroid ? "android" : "ios"; |
| | | params["packages"] = "com.dw.zzql"; |
| | | if (Platform.isAndroid) { |
| | | if (Global.utdId != null) { |
| | | params["utdId"] = Global.utdId; |
| | | } |
| | | params["osVersion"] = _androidInfo!.version.release; |
| | | } else if (Platform.isIOS) { |
| | | params["device"] = _iosInfo!.identifierForVendor; |
| | | } |
| | | |
| | | if (Global.channel != null) { |
| | | params["channel"] = Global.channel; |
| | | } |
| | | |
| | | params["sign"] = _getSign(params); |
| | | |
| | | return params; |
| | | } |
| | | |
| | | static Future<HttpRequestResult> baseRequest( |
| | | String api, Map<String, dynamic> params, OnHttpRequestStart? onStart, |
| | | {bool notifyError = false}) async { |
| | | // params ??= {}; |
| | | params = await getBaseParams(params); |
| | | |
| | | var httpClient = HttpClient(); |
| | | httpClient.connectionTimeout = const Duration(seconds: 20); |
| | | var uri = Uri( |
| | | scheme: "http", |
| | | host: "api.location.izzql.com", |
| | | path: api, |
| | | port: 8090, |
| | | queryParameters: params); |
| | | |
| | | // var uri = Uri( |
| | | // scheme: "http", |
| | | // host: "192.168.3.122", |
| | | // path: api, |
| | | // port: 8082, |
| | | // queryParameters: params); |
| | | |
| | | print("uri:$uri"); |
| | | |
| | | if (onStart != null) { |
| | | onStart(); |
| | | } |
| | | HttpRequestResult requestResult; |
| | | |
| | | try { |
| | | HttpClientRequest request = await httpClient.postUrl(uri); |
| | | var response = await request.close(); |
| | | if (response.statusCode == HttpStatus.ok) { |
| | | String result = await response.transform(const Utf8Decoder()).join(); |
| | | requestResult = HttpRequestResult(true, jsonDecode(result)); |
| | | } else { |
| | | requestResult = HttpRequestResult(false, null, msg: "网络请求失败"); |
| | | } |
| | | } on TimeoutException catch (_) { |
| | | requestResult = HttpRequestResult(false, null, msg: "网络请求超时"); |
| | | } on SocketException catch (_) { |
| | | Fluttertoast.showToast(msg: "网络请求出错"); |
| | | requestResult = HttpRequestResult(false, null, msg: "网络请求出错"); |
| | | } |
| | | if (notifyError && !requestResult.success) { |
| | | ToastUtil.toast(requestResult.msg!); |
| | | } |
| | | return requestResult; |
| | | } |
| | | } |
| | | |
| | | class UserApiUtil { |
| | | ///验证码发送 |
| | | static Future<Map<String, dynamic>?> sendSMS( |
| | | BuildContext context, String phone) async { |
| | | var result = |
| | | await HttpUtil.baseRequest("/api/v1/sms/sendSMS", {"phone": phone}, () { |
| | | showLoading(context); |
| | | }); |
| | | dismissDialog(context); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | static Future<Map<String, dynamic>?> uploadPushRegId( |
| | | BuildContext context, String regId) async { |
| | | var uid = await UserUtil.getUid(); |
| | | var params = {"regId": regId}; |
| | | if (uid != null) { |
| | | params["uid"] = uid.toString(); |
| | | } |
| | | |
| | | var result = await HttpUtil.baseRequest( |
| | | "/api/v1/user/uploadPushRegId", params, () {}); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | ///登录 |
| | | static Future<Map<String, dynamic>?> login( |
| | | BuildContext context, String phone, String vcode, String token) async { |
| | | Map<String, dynamic> params = {}; |
| | | params["phone"] = phone; |
| | | if (!StringUtil.isNullOrEmpty(vcode)) { |
| | | params["vcode"] = vcode; |
| | | } |
| | | |
| | | if (!StringUtil.isNullOrEmpty(token)) { |
| | | params["token"] = token; |
| | | } |
| | | |
| | | var result = |
| | | await HttpUtil.baseRequest("/api/v1/user/loginPhone", params, () { |
| | | showLoading(context); |
| | | }, notifyError: true); |
| | | dismissDialog(context); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | ///获取用户信息 |
| | | static Future<Map<String, dynamic>?> getUserInfo( |
| | | BuildContext context, int uid) async { |
| | | Map<String, dynamic> params = {}; |
| | | params["uid"] = uid.toString(); |
| | | var result = |
| | | await HttpUtil.baseRequest("/api/v1/user/getUserInfo", params, () {}); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | ///退出登录 |
| | | static Future<Map<String, dynamic>?> logout( |
| | | BuildContext context, int? uid) async { |
| | | Map<String, dynamic> params = {}; |
| | | params["uid"] = uid.toString(); |
| | | var result = |
| | | await HttpUtil.baseRequest("/api/v1/user/logout", params, () {}); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | class FeedBackApiUtil { |
| | | ///查阅向我求救的SOS |
| | | static Future<Map<String, dynamic>?> advice( |
| | | BuildContext context, String? type, String content) async { |
| | | var uid = await UserUtil.getUid(); |
| | | Map<String, dynamic> params = {}; |
| | | if (uid != null) { |
| | | params["uid"] = uid.toString(); |
| | | } |
| | | |
| | | if (type != null) { |
| | | params["type"] = type; |
| | | } |
| | | |
| | | params["content"] = content; |
| | | var result = |
| | | await HttpUtil.baseRequest("/api/v1/feedback/advice", params, () { |
| | | showLoading(context); |
| | | }, notifyError: true); |
| | | |
| | | dismissDialog(context); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | class ConfigApiUtil { |
| | | ///查阅向我求救的SOS |
| | | static Future<Map<String, dynamic>?> getConfig() async { |
| | | var result = await HttpUtil.baseRequest( |
| | | "/api/v1/config/getConfig", {}, () {}, |
| | | notifyError: true); |
| | | if (result.success) { |
| | | return result.data; |
| | | } |
| | | return null; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import './api/http.dart'; |
| | | import './utils/ad_util.dart'; |
| | | import './utils/app_util.dart'; |
| | | import './utils/config_util.dart'; |
| | | import './utils/pageutils.dart'; |
| | | import './utils/permission_util.dart'; |
| | | import './utils/ui_utils.dart'; |
| | | import './utils/user_util.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | |
| | | import 'ui/main/main.dart'; |
| | | import 'ui/widget/dialog.dart'; |
| | | import 'utils/ui_constant.dart'; |
| | | import 'utils/global.dart'; |
| | | |
| | | void main() { |
| | | if (Platform.isAndroid) { |
| | | SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle( |
| | | statusBarColor: Colors.transparent, |
| | | systemNavigationBarColor: Colors.white, |
| | | systemNavigationBarDividerColor: null, |
| | | systemNavigationBarIconBrightness: Brightness.light, |
| | | statusBarIconBrightness: Brightness.dark, |
| | | statusBarBrightness: Brightness.light, |
| | | )); |
| | | } |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: Constant.APP_NAME, |
| | | theme: ThemeData( |
| | | // This is the theme of your application. |
| | | // |
| | | // Try running your application with "flutter run". You'll see the |
| | | // application has a blue toolbar. Then, without quitting the app, try |
| | | // changing the primarySwatch below to Colors.green and then invoke |
| | | // "hot reload" (press "r" in the console where you ran "flutter run", |
| | | // or simply save your changes to "hot reload" in a Flutter IDE). |
| | | // Notice that the counter didn't reset back to zero; the application |
| | | // is not restarted. |
| | | |
| | | primaryColor: const Color(0xFFFFFFFF)), |
| | | home: SplashPage(title: ''), |
| | | navigatorKey: navigatorKey); |
| | | } |
| | | } |
| | | |
| | | class SplashPage extends StatefulWidget { |
| | | SplashPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _SplashPageState createState() => _SplashPageState(); |
| | | } |
| | | |
| | | class _SplashPageState extends State<SplashPage> |
| | | with SingleTickerProviderStateMixin { |
| | | int selectIndex = 1; |
| | | Widget? _splash; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | } |
| | | |
| | | bool _jumpToMain = false; |
| | | |
| | | void init() async { |
| | | //请求配置信息 |
| | | var value = await ConfigApiUtil.getConfig(); |
| | | if (value != null) { |
| | | ConfigUtil.saveConfig(value["data"]); |
| | | } |
| | | |
| | | await AppUtil.initApp(context); |
| | | |
| | | Widget splash = AdUtil.loadSplash( |
| | | await AdUtil.getAdInfo(AdPosition.splash), |
| | | MediaQuery.of(context).size.width, |
| | | MediaQuery.of(context).size.height - 94, (success, msg) { |
| | | if (_jumpToMain == true) { |
| | | return; |
| | | } |
| | | _jumpToMain = true; |
| | | if (success) { |
| | | NavigatorUtil.navigateToNextPageWithFinish(context, |
| | | CupertinoPageRoute(builder: (context) { |
| | | return MainPage(title: ""); |
| | | })); |
| | | } else { |
| | | Future.delayed(const Duration(seconds: 2), () { |
| | | NavigatorUtil.navigateToNextPageWithFinish(context, |
| | | CupertinoPageRoute(builder: (context) { |
| | | return MainPage(title: ""); |
| | | })); |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | setState(() { |
| | | _splash = splash; |
| | | }); |
| | | } |
| | | |
| | | Future requestPermission() async { |
| | | await PermissionUtil.openPermission(Permission.phone); |
| | | // await PermissionUtil.openPermission(PermissionUtil.getLocationPermission()); |
| | | return; |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | UserUtil.isAgreeProtocol().then((value) { |
| | | if (!value) { |
| | | //弹出用户协议框 |
| | | String content = "尊敬的用户:<br>" + |
| | | "感谢您对定位App一直以来的信任!<br>" + |
| | | "我们非常重视保护您的个人信息和隐私。在您使用我们的软件前,为了更好的保障您的权利,请务必阅读<a href='${Constant.PROTOCOL_URL}'>《用户协议》</a>和<a href='${Constant.PRIVACY_URL}'>《隐私政策》</a>,您同意并接受所有条款后,才能使用我们软件。若您注册成为本软件会员或接受好友的邀请即表明您允许向本软件中的好友提供您的地理位置和轨迹等信息。为确保软件正常运行我们需要获得,尤其是:<br>" + |
| | | "1、我们对您的个人信息(包括但不限于<b style='color:red'>设备MAC地址、IMEI/Android ID、位置信息</b>等信息)的收集/保存/使用/对外提供/保护等规则条款,以及您的用户权利等条款;<br>" + |
| | | "2、约定我们的限制责任、免责条款;<br>" + |
| | | "3、其他以加粗或斜体字进行标识的重要条款。<br>" + |
| | | "4、特别申明:本软件定位守护等功能需双方都下载本软件并同意授权后才可正常使用,不涉及侵犯个人隐私问题。获取地理信息必须在用户双方知情并同意的情况下进行,本软件仅限用于家庭/亲友/熟人/朋友间使用。<br>" + |
| | | "如您对协议有任何疑虑,可通过电子邮箱:dw365@foxmail.com 向我们询问,我们将为您竭诚解答。您点击“同意并继续”的行为代表您已阅读完毕并接受以上协议全部条款。如您同意以上协议内容,请您点击“同意并继续”,开始使用本软件。"; |
| | | |
| | | DialogUtil.showDialog( |
| | | context, |
| | | NotifyDialog("用户协议&隐私政策", content, () { |
| | | SystemNavigator.pop(); |
| | | }, () { |
| | | UserUtil.setAgreeProtocol().then((value) { |
| | | if (value) { |
| | | //弹出权限框 |
| | | DialogUtil.showDialog(context, PermissionNotifyDialog(() { |
| | | Navigator.of(context).pop(); |
| | | requestPermission().then((value) { |
| | | init(); |
| | | }); |
| | | })); |
| | | } else {} |
| | | }); |
| | | }, |
| | | richText: true, |
| | | height: 400, |
| | | cancelName: "不同意", |
| | | sureName: "同意并继续")); |
| | | } else { |
| | | //已经同意了 |
| | | init(); |
| | | } |
| | | }); |
| | | |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Scaffold( |
| | | backgroundColor: Colors.white, |
| | | body: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Expanded( |
| | | child: Stack(children: [ |
| | | Container( |
| | | alignment: Alignment.center, |
| | | padding: const EdgeInsets.all(72), |
| | | color: Colors.white, |
| | | child: Image.asset("assets/images/ic_splash.png"), |
| | | ), |
| | | _splash != null ? _splash! : Container() |
| | | ])), |
| | | Container( |
| | | alignment: Alignment.center, |
| | | color: const Color(0xFFF8F8F8), |
| | | height: 94, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: const [ |
| | | Text( |
| | | Constant.APP_NAME, |
| | | style: |
| | | TextStyle(color: Color(0xFF03B5FF), fontSize: 23), |
| | | ), |
| | | SizedBox( |
| | | height: 15, |
| | | ), |
| | | Text( |
| | | "腾讯云提供网络服务", |
| | | style: TextStyle(color: Color(0xFF999999), fontSize: 9), |
| | | ), |
| | | ], |
| | | ), |
| | | ) |
| | | ], |
| | | ))); |
| | | } |
| | | } |
New file |
| | |
| | | /// type : "csj" |
| | | /// pid : "123456" |
| | | |
| | | class AdinfoModel { |
| | | AdinfoModel({ |
| | | String? type, |
| | | String? pid,}){ |
| | | _type = type; |
| | | _pid = pid; |
| | | } |
| | | |
| | | AdinfoModel.fromJson(dynamic json) { |
| | | _type = json['type']; |
| | | _pid = json['pid']; |
| | | } |
| | | String? _type; |
| | | String? _pid; |
| | | |
| | | String? get type => _type; |
| | | String? get pid => _pid; |
| | | |
| | | Map<String, dynamic> toJson() { |
| | | final map = <String, dynamic>{}; |
| | | map['type'] = _type; |
| | | map['pid'] = _pid; |
| | | return map; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | import '../../api/http.dart'; |
| | | |
| | | class HttpRequestResult { |
| | | final Map<String, dynamic>? data; |
| | | final bool success; |
| | | final String? msg; |
| | | |
| | | HttpRequestResult(this.success, this.data, {this.msg}); |
| | | } |
| | | |
| | | class HttpRequestListener { |
| | | OnHttpRequestFinish? onFinish; |
| | | OnHttpRequestStart? onStart; |
| | | |
| | | HttpRequestListener({this.onStart, this.onFinish}); |
| | | } |
New file |
| | |
| | | ///用户信息 |
| | | class UserInfo { |
| | | UserInfo( |
| | | {int? id, |
| | | String? nickName, |
| | | String? portrait, |
| | | int? vipExpireTime, |
| | | bool? needAlwaysLocation}) { |
| | | _id = id; |
| | | _nickName = nickName; |
| | | _portrait = portrait; |
| | | _vipExpireTime = vipExpireTime; |
| | | } |
| | | |
| | | UserInfo.fromJson(dynamic json) { |
| | | _id = int.parse(json['id'].toString()); |
| | | _nickName = json['nickName']; |
| | | _portrait = json['portrait']; |
| | | _vipExpireTime = json['vipExpireTime']; |
| | | } |
| | | |
| | | int? _id; |
| | | String? _nickName; |
| | | String? _portrait; |
| | | int? _vipExpireTime; |
| | | |
| | | int? get id => _id; |
| | | |
| | | String? get nickName => _nickName; |
| | | |
| | | String? get portrait => _portrait; |
| | | |
| | | int? get vipExpireTime => _vipExpireTime; |
| | | |
| | | |
| | | Map<String, dynamic> toJson() { |
| | | final map = <String, dynamic>{}; |
| | | map['id'] = _id; |
| | | map['nickName'] = _nickName; |
| | | map['portrait'] = _portrait; |
| | | map['vipExpireTime'] = _vipExpireTime; |
| | | return map; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:io'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:url_launcher/url_launcher.dart'; |
| | | import 'package:webview_flutter/webview_flutter.dart'; |
| | | |
| | | import '../../ui/widget/nav.dart'; |
| | | import '../../utils/jsinterface.dart'; |
| | | |
| | | class BrowserPage extends StatefulWidget { |
| | | BrowserPage({Key? key, required this.title, required this.url}) |
| | | : super(key: key); |
| | | final String title; |
| | | final String url; |
| | | |
| | | @override |
| | | _BrowserPageState createState() => _BrowserPageState(title, url); |
| | | } |
| | | |
| | | class _BrowserPageState extends State<BrowserPage> |
| | | with SingleTickerProviderStateMixin { |
| | | String title = ""; |
| | | String? url; |
| | | double progress = 0; |
| | | |
| | | _BrowserPageState(this.title, this.url); |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | if (Platform.isAndroid) { |
| | | WebView.platform = SurfaceAndroidWebView(); |
| | | } |
| | | } |
| | | |
| | | WebViewController? _webViewController; |
| | | |
| | | _back() { |
| | | if (_webViewController == null) { |
| | | Navigator.of(context).pop(); |
| | | } else { |
| | | _webViewController!.canGoBack().then((value) { |
| | | if (value) { |
| | | _webViewController!.goBack(); |
| | | } else { |
| | | Navigator.of(context).pop(); |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | _back(); |
| | | return false; |
| | | }, |
| | | child: Scaffold( |
| | | backgroundColor: Colors.white, |
| | | body: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | TopNavBar( |
| | | title: title, |
| | | back: () { |
| | | _back(); |
| | | }, |
| | | rightIcon: Image.asset( |
| | | "assets/imgs/common/icon_refresh.png", |
| | | width: 22, |
| | | ), |
| | | rightClick: (){ |
| | | if(_webViewController!=null){ |
| | | _webViewController!.reload(); |
| | | } |
| | | }, |
| | | ), |
| | | SizedBox( |
| | | height: 1, |
| | | child: LinearProgressIndicator( |
| | | backgroundColor: Colors.white, |
| | | valueColor: const AlwaysStoppedAnimation(Color(0xFF0E96FF)), |
| | | value: progress, |
| | | ), |
| | | ), |
| | | Expanded( |
| | | child: WebView( |
| | | //http://192.168.3.122:8848/test/JsTest.html |
| | | initialUrl: url, |
| | | onWebViewCreated: (WebViewController webViewController) { |
| | | _webViewController = webViewController; |
| | | }, |
| | | javascriptMode: JavascriptMode.unrestricted, |
| | | javascriptChannels: |
| | | JavascriptInterface(context, _webViewController) |
| | | .getInterfaces(), |
| | | navigationDelegate: (NavigationRequest request) { |
| | | print("链接:${request.url}"); |
| | | if (!request.url.startsWith("http")) { |
| | | launch(request.url); |
| | | return NavigationDecision.prevent; |
| | | } |
| | | return NavigationDecision.navigate; |
| | | }, |
| | | onPageStarted: (url) { |
| | | print("process:onPageStarted-$url"); |
| | | }, |
| | | onPageFinished: (url) { |
| | | print("process:onPageFinished-$url"); |
| | | _webViewController!.getTitle().then((value) { |
| | | if (value != null) { |
| | | setState(() { |
| | | title = value; |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | onProgress: (int process) { |
| | | print("process:$process"); |
| | | setState(() { |
| | | if (process == 100) { |
| | | progress = 0; |
| | | } else { |
| | | progress = process / 100.0; |
| | | } |
| | | }); |
| | | }, |
| | | )) |
| | | ], |
| | | ))); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import '../../api/http.dart'; |
| | | import '../../ui/widget/dialog.dart'; |
| | | import '../../utils/ad_util.dart'; |
| | | import '../../utils/event_bus_util.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | import '../../utils/ui_utils.dart'; |
| | | import '../../utils/user_util.dart'; |
| | | import 'mine.dart'; |
| | | |
| | | void main() { |
| | | if (Platform.isAndroid) { |
| | | SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( |
| | | statusBarColor: Colors.transparent, |
| | | systemNavigationBarColor: Color(0xFF000000), |
| | | systemNavigationBarDividerColor: null, |
| | | systemNavigationBarIconBrightness: Brightness.light, |
| | | statusBarIconBrightness: Brightness.dark, |
| | | statusBarBrightness: Brightness.light, |
| | | )); |
| | | } |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: 'Flutter Demo', |
| | | theme: ThemeData( |
| | | // This is the theme of your application. |
| | | // |
| | | // Try running your application with "flutter run". You'll see the |
| | | // application has a blue toolbar. Then, without quitting the app, try |
| | | // changing the primarySwatch below to Colors.green and then invoke |
| | | // "hot reload" (press "r" in the console where you ran "flutter run", |
| | | // or simply save your changes to "hot reload" in a Flutter IDE). |
| | | // Notice that the counter didn't reset back to zero; the application |
| | | // is not restarted. |
| | | |
| | | primaryColor: Color(0xFFFFFFFF)), |
| | | home: MainPage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class MainPage extends StatefulWidget { |
| | | MainPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _MainPageState createState() => _MainPageState(); |
| | | } |
| | | |
| | | class _MainPageState extends State<MainPage> |
| | | with SingleTickerProviderStateMixin { |
| | | int selectIndex = 1; |
| | | List<Widget> _pages = <Widget>[]; |
| | | TabController? _tabController; |
| | | |
| | | @override |
| | | void initState() { |
| | | _pages |
| | | // ..add(KeepAliveWrapper(child: MainTravelPage())) |
| | | // ..add(KeepAliveWrapper(child: LocationPage(title: "定位"))) |
| | | ..add(KeepAliveWrapper(child: MinePage(title: "我的"))); |
| | | _tabController = |
| | | TabController(length: _pages.length, initialIndex: 1, vsync: this); |
| | | super.initState(); |
| | | |
| | | Timer(const Duration(seconds: 1), () { |
| | | AdUtil.getAdInfo(AdPosition.homeInterstitial).then((value) { |
| | | AdUtil.loadInterstitial(value, (success, msg) {}); |
| | | }); |
| | | }); |
| | | |
| | | UserUtil.updateUserInfo(context); |
| | | } |
| | | |
| | | int lastCenterClick = 0; |
| | | |
| | | //设置选中的导航栏 |
| | | void setSelectIndex(int i) { |
| | | if (i == selectIndex) { |
| | | if (selectIndex == 1) { |
| | | if (DateTime.now().millisecondsSinceEpoch - lastCenterClick < 400) { |
| | | print("双击"); |
| | | } else { |
| | | //单击 |
| | | Future.delayed(const Duration(milliseconds: 400), () { |
| | | if (DateTime.now().millisecondsSinceEpoch - lastCenterClick < |
| | | 400) { |
| | | return; |
| | | } |
| | | print("单击"); |
| | | }); |
| | | |
| | | |
| | | } |
| | | lastCenterClick = DateTime.now().millisecondsSinceEpoch; |
| | | } |
| | | return; |
| | | } |
| | | setState(() { |
| | | selectIndex = i; |
| | | }); |
| | | print("setSelectIndex"); |
| | | _tabController!.animateTo(i); |
| | | } |
| | | |
| | | int lastBack = 0; |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | if (DateTime.now().millisecondsSinceEpoch - lastBack > 1000 * 5) { |
| | | lastBack = DateTime.now().millisecondsSinceEpoch; |
| | | ToastUtil.toast("再按一次退出应用"); |
| | | return false; |
| | | } else { |
| | | return true; |
| | | } |
| | | }, |
| | | child: Scaffold( |
| | | backgroundColor: Colors.white, |
| | | resizeToAvoidBottomInset: false, |
| | | body: Container( |
| | | child: Stack( |
| | | children: [ |
| | | //内容栏 |
| | | Container( |
| | | color: Colors.white, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Expanded( |
| | | child: TabBarView( |
| | | controller: _tabController, |
| | | children: _pages, |
| | | physics: const NeverScrollableScrollPhysics(), |
| | | )), |
| | | Container( |
| | | height: 60, |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | |
| | | //底部导航栏 |
| | | Positioned( |
| | | bottom: 0, |
| | | child: Container( |
| | | child: Stack( |
| | | alignment: Alignment.bottomCenter, |
| | | children: [ |
| | | Container( |
| | | height: 60, |
| | | width: MediaQuery.of(context).size.width, |
| | | alignment: Alignment.center, |
| | | decoration: |
| | | BoxDecoration(color: Colors.white, boxShadow: [ |
| | | BoxShadow( |
| | | blurRadius: 10, |
| | | spreadRadius: 1, |
| | | color: Color(0x4D0E96FF), |
| | | ) |
| | | ]), |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Expanded( |
| | | child: getNavItem( |
| | | icon: Image.asset( |
| | | "assets/imgs/main/icon_main_nav_history.png", |
| | | width: 31, |
| | | ), |
| | | iconHighlight: Image.asset( |
| | | "assets/imgs/main/icon_main_nav_history_highlight.png", |
| | | width: 31, |
| | | ), |
| | | text: "轨迹", |
| | | index: 0)), |
| | | Container( |
| | | width: 54, |
| | | ), |
| | | Expanded( |
| | | child: getNavItem( |
| | | icon: Image.asset( |
| | | "assets/imgs/main/icon_main_nav_mine.png", |
| | | width: 31), |
| | | iconHighlight: Image.asset( |
| | | "assets/imgs/main/icon_main_nav_mine_highlight.png", |
| | | width: 31), |
| | | text: "我的", |
| | | index: 2)), |
| | | ], |
| | | ), |
| | | ), |
| | | Positioned( |
| | | child: Container( |
| | | height: 72, |
| | | width: 72, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.circular(36), |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | blurRadius: 10, |
| | | spreadRadius: 1, |
| | | color: Color(0x4D0E96FF)) |
| | | ]), |
| | | ), |
| | | ), |
| | | Container( |
| | | height: 60, |
| | | width: 100, |
| | | color: Colors.white, |
| | | ), |
| | | Container( |
| | | height: 72, |
| | | width: 72, |
| | | alignment: Alignment.center, |
| | | child: getNavLocationItem(), |
| | | ) |
| | | ], |
| | | ))) |
| | | ], |
| | | ), |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | Widget getNavItem( |
| | | {required Image icon, |
| | | required Image iconHighlight, |
| | | required String text, |
| | | required int index}) { |
| | | return Container( |
| | | alignment: Alignment.center, |
| | | child: InkWell( |
| | | onTap: () { |
| | | setSelectIndex(index); |
| | | }, |
| | | child: Flex( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | selectIndex == index ? iconHighlight : icon, |
| | | Text( |
| | | text, |
| | | style: TextStyle( |
| | | fontSize: 15, |
| | | color: selectIndex == index |
| | | ? ColorConstant.theme |
| | | : Color(0xFF9DAAB3)), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | Widget getNavLocationItem() { |
| | | return InkWell( |
| | | onTap: () { |
| | | setSelectIndex(1); |
| | | }, |
| | | child: Container( |
| | | width: 54, |
| | | height: 54, |
| | | decoration: BoxDecoration( |
| | | color: selectIndex == 1 ? ColorConstant.theme : Color(0xFF9DAAB3), |
| | | borderRadius: BorderRadius.circular(27), |
| | | boxShadow: selectIndex == 1 |
| | | ? [ |
| | | BoxShadow( |
| | | blurRadius: 3, |
| | | spreadRadius: 2, |
| | | color: Color(0x4D0E96FF)) |
| | | ] |
| | | : []), |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/main/icon_main_nav_location.png", |
| | | height: 25, |
| | | ), |
| | | Container( |
| | | height: 3, |
| | | ), |
| | | const Text( |
| | | "定位", |
| | | style: TextStyle(color: Colors.white, fontSize: 9), |
| | | ) |
| | | ], |
| | | ), |
| | | )); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import '../../ui/mine/settings.dart'; |
| | | import '../../ui/mine/login.dart'; |
| | | import '../../ui/mine/advice.dart'; |
| | | import '../../api/http.dart'; |
| | | import '../../model/user/user_info.dart'; |
| | | import '../../ui/common/browser.dart'; |
| | | import '../../utils/ad_util.dart'; |
| | | import '../../utils/config_util.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | import '../../utils/string_util.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | import '../../utils/ui_utils.dart'; |
| | | import '../../utils/user_util.dart'; |
| | | |
| | | void main() { |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: 'Flutter Demo', |
| | | theme: ThemeData( |
| | | // This is the theme of your application. |
| | | // |
| | | // Try running your application with "flutter run". You'll see the |
| | | // application has a blue toolbar. Then, without quitting the app, try |
| | | // changing the primarySwatch below to Colors.green and then invoke |
| | | // "hot reload" (press "r" in the console where you ran "flutter run", |
| | | // or simply save your changes to "hot reload" in a Flutter IDE). |
| | | // Notice that the counter didn't reset back to zero; the application |
| | | // is not restarted. |
| | | primaryColor: Color.fromARGB(255, 150, 150, 150)), |
| | | home: MinePage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class MinePage extends StatefulWidget { |
| | | MinePage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _MinePageState createState() => _MinePageState(); |
| | | } |
| | | |
| | | class _MinePageState extends State<MinePage> |
| | | with AutomaticKeepAliveClientMixin { |
| | | UserInfo? userInfo = null; |
| | | bool isLogin = false; |
| | | bool isVIP = false; |
| | | List<Widget> list = []; |
| | | Widget? adView; |
| | | bool adDeleted = false; |
| | | final List<Functions> data = [ |
| | | Functions("assets/imgs/mine/icon_mine_permission.png", "权限设置", |
| | | "permission", false), |
| | | ]; |
| | | |
| | | void _onClick(Functions function) async { |
| | | if (function.needLogin) { |
| | | bool login = await UserUtil.isLogin(); |
| | | if (!login) { |
| | | NavigatorUtil.navigateToNextPage(context, LoginPage(title: ""), (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | int? uid = await UserUtil.getUid(); |
| | | |
| | | switch (function.key) { |
| | | case "kefu": |
| | | ConfigUtil.getConfig(ConfigKey.kefu).then((value) { |
| | | if (!StringUtil.isNullOrEmpty(value)) { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, BrowserPage(title: "在线客服", url: value!), (data) {}); |
| | | } |
| | | }); |
| | | break; |
| | | |
| | | case "advice": |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, AdvicePage(title: ""), (data) {}); |
| | | break; |
| | | case "protocol": |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | BrowserPage( |
| | | title: "用户协议", |
| | | url: Constant.PROTOCOL_URL, |
| | | ), |
| | | (data) {}); |
| | | break; |
| | | case "privacy": |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | BrowserPage( |
| | | title: "隐私政策", |
| | | url: Constant.PRIVACY_URL, |
| | | ), |
| | | (data) {}); |
| | | break; |
| | | case "setting": |
| | | NavigatorUtil.navigateToNextPage(context, SettingPage(title: ""), |
| | | (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | |
| | | break; |
| | | } |
| | | } |
| | | |
| | | @override |
| | | void initState() { |
| | | data.forEach((item) { |
| | | list.add(InkWell( |
| | | child: Column( |
| | | children: [ |
| | | Image.asset(item.icon, height: 31), |
| | | Container( |
| | | child: Text( |
| | | item.name, |
| | | style: new TextStyle(color: ColorConstant.theme), |
| | | ), |
| | | margin: const EdgeInsets.fromLTRB(0, 13, 0, 0)) |
| | | ], |
| | | ), |
| | | onTap: () { |
| | | _onClick(item); |
| | | }, |
| | | )); |
| | | }); |
| | | |
| | | //获取用户信息 |
| | | _getUserInfo(); |
| | | |
| | | super.initState(); |
| | | } |
| | | |
| | | void _login() { |
| | | NavigatorUtil.navigateToNextPage(context, LoginPage(title: ""), (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | } |
| | | |
| | | void _loadAd() async { |
| | | if (adView != null) { |
| | | return; |
| | | } |
| | | if (adDeleted) { |
| | | return; |
| | | } |
| | | |
| | | Widget? ad = AdUtil.loadExpress( |
| | | await AdUtil.getAdInfo(AdPosition.mineExpress), |
| | | MediaQuery.of(context).size.width - 20, |
| | | 200, (success, msg) { |
| | | adDeleted = true; |
| | | setState(() { |
| | | adView = null; |
| | | }); |
| | | }); |
| | | |
| | | setState(() { |
| | | adView = ad; |
| | | }); |
| | | } |
| | | |
| | | void _getUserInfo() async { |
| | | var user = await UserUtil.getUserInfo(); |
| | | if (user == null) { |
| | | setState(() { |
| | | isLogin = false; |
| | | userInfo = null; |
| | | }); |
| | | return; |
| | | } |
| | | setState(() { |
| | | isLogin = true; |
| | | userInfo = user; |
| | | }); |
| | | |
| | | Map<String, dynamic>? result = |
| | | await UserApiUtil.getUserInfo(context, user.id!); |
| | | var code = result!["code"]; |
| | | if (code == 0) { |
| | | UserInfo user = UserInfo.fromJson(result["data"]); |
| | | //保存用户信息 |
| | | UserUtil.setUserInfo(user); |
| | | setState(() { |
| | | userInfo = user; |
| | | if (userInfo != null && |
| | | userInfo!.vipExpireTime != null && |
| | | userInfo!.vipExpireTime! > DateTime.now().millisecondsSinceEpoch) { |
| | | isVIP = true; |
| | | } else { |
| | | isVIP = false; |
| | | } |
| | | }); |
| | | } else if (code == 80001) { |
| | | //账号被封禁 |
| | | setState(() { |
| | | isLogin = false; |
| | | }); |
| | | ToastUtil.toast("账号已被封禁"); |
| | | await UserUtil.logout(); |
| | | } else if (code == 80002) { |
| | | //账号被删除 |
| | | setState(() { |
| | | isLogin = false; |
| | | }); |
| | | ToastUtil.toast("账号已被删除"); |
| | | await UserUtil.logout(); |
| | | } |
| | | } |
| | | |
| | | Widget getLoginContentView() { |
| | | if (isLogin) { |
| | | return getUserInfoWidget(); |
| | | } else { |
| | | return getLoginBtnWidget(); |
| | | } |
| | | } |
| | | |
| | | Widget getLoginBtnWidget() { |
| | | return Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | _login(); |
| | | }, |
| | | child: Container( |
| | | margin: const EdgeInsets.fromLTRB(10, 0, 10, 0), |
| | | height: 38, |
| | | alignment: Alignment.center, |
| | | child: const Text( |
| | | "登录/注册", |
| | | style: TextStyle(color: Colors.white, fontSize: 15), |
| | | ), |
| | | decoration: const BoxDecoration( |
| | | color: Color(0xFF0E96FF), |
| | | borderRadius: BorderRadius.all(Radius.elliptical(10, 10))), |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | Widget getUserInfoWidget() { |
| | | return Container( |
| | | height: 50, |
| | | padding: EdgeInsets.zero, |
| | | margin: const EdgeInsets.fromLTRB(10, 0, 0, 0), |
| | | alignment: Alignment.topLeft, |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | mainAxisAlignment: MainAxisAlignment.start, |
| | | children: [ |
| | | Text( |
| | | userInfo!.nickName!, |
| | | style: const TextStyle(color: Color(0xFF40C7FF), fontSize: 18), |
| | | ), |
| | | Text( |
| | | "ID:" + userInfo!.id!.toString(), |
| | | style: const TextStyle(color: Color(0xFF40C7FF), fontSize: 12), |
| | | ), |
| | | ], |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | Widget _getVIPLeftTime() { |
| | | List<TextSpan> spanList = [const TextSpan(text: '剩余')]; |
| | | if (userInfo != null && userInfo!.vipExpireTime != null) { |
| | | int leftTime = |
| | | userInfo!.vipExpireTime! - DateTime.now().millisecondsSinceEpoch; |
| | | leftTime = leftTime ~/ 1000; |
| | | if (leftTime >= 60 * 60 * 24) { |
| | | spanList.add(TextSpan( |
| | | text: '${leftTime ~/ (60 * 60 * 24)}', |
| | | style: const TextStyle(fontWeight: FontWeight.bold))); |
| | | spanList.add(const TextSpan(text: '天到期')); |
| | | } else if (leftTime >= 60 * 60) { |
| | | spanList.add(TextSpan( |
| | | text: '${leftTime ~/ (60 * 60)}', |
| | | style: const TextStyle(fontWeight: FontWeight.bold))); |
| | | spanList.add(const TextSpan(text: '小时到期')); |
| | | } else { |
| | | spanList.add(TextSpan( |
| | | text: '${leftTime ~/ (60)}', |
| | | style: const TextStyle(fontWeight: FontWeight.bold))); |
| | | spanList.add(const TextSpan(text: '分钟到期')); |
| | | } |
| | | } |
| | | |
| | | return Text.rich(TextSpan( |
| | | children: spanList, |
| | | style: const TextStyle(color: Colors.white, fontSize: 17.5), |
| | | )); |
| | | } |
| | | |
| | | List<Widget> getVIPContent() { |
| | | List<Widget> list = []; |
| | | list.add(Image.asset( |
| | | "assets/imgs/mine/icon_vip.png", |
| | | width: 44, |
| | | )); |
| | | if (isVIP&&userInfo!=null) { |
| | | list.add(Container( |
| | | margin: const EdgeInsets.fromLTRB(6, 0, 0, 0), |
| | | child: _getVIPLeftTime())); |
| | | } else { |
| | | list.add(Container( |
| | | margin: const EdgeInsets.fromLTRB(6, 0, 0, 0), |
| | | child: Image.asset( |
| | | "assets/imgs/mine/label_vip.png", |
| | | height: 20, |
| | | ), |
| | | )); |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | _loadAd(); |
| | | return Scaffold( |
| | | backgroundColor: Colors.white, |
| | | body: SingleChildScrollView( |
| | | child: Column( |
| | | children: [ |
| | | Container( |
| | | decoration: const BoxDecoration( |
| | | image: DecorationImage( |
| | | image: |
| | | AssetImage("assets/imgs/mine/ic_mine_top_bg.png"), |
| | | fit: BoxFit.cover)), |
| | | height: 350, |
| | | width: 400, |
| | | padding: const EdgeInsets.all(10), |
| | | child: Column( |
| | | children: [ |
| | | //登录与用户信息 |
| | | Container( |
| | | margin: EdgeInsets.fromLTRB(0, 105, 0, 0), |
| | | padding: EdgeInsets.all(15), |
| | | alignment: Alignment.centerLeft, |
| | | child: Container( |
| | | height: 50, |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/mine/icon_mine_default_portrait.png", |
| | | width: 50, |
| | | ), |
| | | //登录按钮 |
| | | getLoginContentView(), |
| | | //信息 |
| | | ], |
| | | )), |
| | | height: 105, |
| | | decoration: const BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: |
| | | BorderRadius.all(Radius.elliptical(10, 10)))), |
| | | //会员 |
| | | Container( |
| | | margin: EdgeInsets.fromLTRB(0, 10, 0, 0), |
| | | height: 105, |
| | | width: 400, |
| | | child: Stack( |
| | | children: [ |
| | | Container( |
| | | padding: const EdgeInsets.fromLTRB(18.5, 0, 0, 0), |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | children: [ |
| | | Flex( |
| | | direction: Axis.horizontal, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: getVIPContent(), |
| | | ), |
| | | Container( |
| | | margin: const EdgeInsets.fromLTRB(0, 8, 0, 0), |
| | | child: const Text( |
| | | "定位守护亲友,黑科技保驾护航", |
| | | style: TextStyle( |
| | | fontSize: 15, color: Colors.white), |
| | | ), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | Positioned( |
| | | right: 0, |
| | | top: 17, |
| | | child: InkWell( |
| | | onTap: () { |
| | | //查看详情或开通 |
| | | print(isVIP ? "查看详情" : "开通会员"); |
| | | UserUtil.isLogin().then((value) { |
| | | if (!value) { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, LoginPage(title: ""), |
| | | (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | child: InkWell( |
| | | onTap: () { |
| | | UserUtil.isLogin().then((value) { |
| | | if (!value) { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, LoginPage(title: ""), |
| | | (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | ConfigUtil.getConfig( |
| | | ConfigKey.vipLink) |
| | | .then((value) { |
| | | if (!StringUtil.isNullOrEmpty( |
| | | value)) { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | BrowserPage( |
| | | title: "会员", |
| | | url: value!), (data) { |
| | | _getUserInfo(); |
| | | }); |
| | | } |
| | | }); |
| | | }); |
| | | }, |
| | | child: Container( |
| | | width: 99, |
| | | height: 26, |
| | | alignment: Alignment.center, |
| | | child: Text( |
| | | isVIP ? "查看详情" : "立即开通", |
| | | style: const TextStyle( |
| | | color: Color(0xFFD4A880)), |
| | | ), |
| | | decoration: const BoxDecoration( |
| | | color: Color(0xFFFAEAB9), |
| | | borderRadius: BorderRadius.only( |
| | | topLeft: Radius.circular(13), |
| | | bottomLeft: |
| | | Radius.circular(13)), |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | color: Color(0x4D0E96FF), |
| | | blurRadius: 2.0, |
| | | offset: Offset(0.0, 3.0), |
| | | //阴影y轴偏移量 |
| | | spreadRadius: 0 //阴影扩散程度 |
| | | ) |
| | | ], |
| | | ))))) |
| | | ], |
| | | ), |
| | | decoration: const BoxDecoration( |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | color: Color(0x4D0E96FF), |
| | | blurRadius: 5.0, |
| | | offset: Offset(0.0, 8.0), //阴影y轴偏移量 |
| | | spreadRadius: 0 //阴影扩散程度 |
| | | ) |
| | | ], |
| | | gradient: LinearGradient( |
| | | stops: [.5, 1], |
| | | colors: [Color(0xFF4699FF), Color(0xFF00DEFF)]), |
| | | color: Colors.white, |
| | | borderRadius: |
| | | BorderRadius.all(Radius.elliptical(10, 10)))) |
| | | ], |
| | | ), |
| | | ), |
| | | |
| | | Container( |
| | | child: adView ?? Container(), |
| | | margin: EdgeInsets.only(left: 10, right: 10), |
| | | ), |
| | | //广告 |
| | | |
| | | //功能区域 |
| | | Container( |
| | | height: 340, |
| | | margin: const EdgeInsets.all(10), |
| | | padding: const EdgeInsets.all(10), |
| | | decoration: const BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.elliptical(10, 10)), |
| | | color: Color(0xFFF4FFFF)), |
| | | child: GridView( |
| | | gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( |
| | | crossAxisCount: 4, mainAxisSpacing: 10), |
| | | physics: const NeverScrollableScrollPhysics(), |
| | | children: list), |
| | | ), |
| | | ], |
| | | ))); |
| | | } |
| | | |
| | | @override |
| | | bool get wantKeepAlive => true; |
| | | } |
| | | |
| | | class Functions { |
| | | Functions(this.icon, this.name, this.key, this.needLogin); |
| | | |
| | | String icon; |
| | | String name; |
| | | String key; |
| | | bool needLogin; |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import '../../ui/widget/nav.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | |
| | | import 'advice_submit.dart'; |
| | | import 'package:launch_review/launch_review.dart'; |
| | | void main() { |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: '意见反馈', |
| | | theme: ThemeData(primaryColor: Color(0xFFF5F5F5)), |
| | | home: AdvicePage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class AdvicePage extends StatefulWidget { |
| | | AdvicePage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _AdvicePageState createState() => _AdvicePageState(); |
| | | } |
| | | |
| | | class _AdvicePageState extends State<AdvicePage> |
| | | with SingleTickerProviderStateMixin { |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | } |
| | | |
| | | BoxDecoration getItemDecoration(Color bgColor, Color shadowColor) { |
| | | return BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.elliptical(10, 10)), |
| | | color: bgColor, |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | color: shadowColor, |
| | | blurRadius: 2.0, |
| | | offset: Offset(0.0, 5.0), //阴影y轴偏移量 |
| | | spreadRadius: 1 //阴影扩散程度 |
| | | ) |
| | | ]); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | backgroundColor: Color(0xFFFFFFFF), |
| | | body: Container( |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | TopNavBar(title: "意见反馈"), |
| | | Image.asset("assets/imgs/advice/ic_advice_top.png"), |
| | | getItemView( |
| | | bgColor: Color(0xFFFFC945), |
| | | shadowColor: Color(0x4DFCA235), |
| | | title: "提意见", |
| | | subTitle: "有建议,请留言", |
| | | icon: "assets/imgs/advice/icon_advice_msg.png", |
| | | onTap: () { |
| | | Navigator.of(context) |
| | | .push(CustomRouteSlide(AdviceSubmitPage(title: ""))); |
| | | }, |
| | | ), |
| | | getItemView( |
| | | bgColor: const Color(0xFF29D5FF), |
| | | shadowColor: const Color(0x4D0E96FF), |
| | | title: "给鼓励", |
| | | subTitle: "您的鼓励是我们前进的动力", |
| | | icon: "assets/imgs/advice/icon_advice_like.png", |
| | | onTap: () { |
| | | |
| | | LaunchReview.launch(); |
| | | }, |
| | | ), |
| | | ], |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | Widget getItemView( |
| | | {required Color bgColor, |
| | | required Color shadowColor, |
| | | required String title, |
| | | required String subTitle, |
| | | required String icon, |
| | | required GestureTapCallback onTap}) { |
| | | return InkWell( |
| | | onTap: () { |
| | | onTap(); |
| | | }, |
| | | child: Container( |
| | | height: 92.5, |
| | | padding: EdgeInsets.fromLTRB(20, 0, 24, 0), |
| | | margin: EdgeInsets.fromLTRB(10, 12.5, 10, 4), |
| | | decoration: getItemDecoration(bgColor, shadowColor), |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | children: [ |
| | | Text( |
| | | title, |
| | | style: TextStyle(color: Colors.white, fontSize: 24), |
| | | ), |
| | | Text( |
| | | subTitle, |
| | | style: TextStyle(color: Colors.white, fontSize: 14), |
| | | ) |
| | | ], |
| | | ), |
| | | Expanded(child: Container()), |
| | | Image.asset( |
| | | icon, |
| | | height: 62, |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | ); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import '../../api/http.dart'; |
| | | import '../../ui/widget/nav.dart'; |
| | | import '../../utils/string_util.dart'; |
| | | import '../../utils/ui_utils.dart'; |
| | | |
| | | void main() { |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: '提意见', |
| | | theme: ThemeData(primaryColor: Color(0xFFF5F5F5)), |
| | | home: AdviceSubmitPage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class AdviceSubmitPage extends StatefulWidget { |
| | | AdviceSubmitPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _AdviceSubmitPageState createState() => _AdviceSubmitPageState(); |
| | | } |
| | | |
| | | class _AdviceSubmitPageState extends State<AdviceSubmitPage> |
| | | with SingleTickerProviderStateMixin { |
| | | List<String> questions = ["账号问题", "定位问题", "其他问题"]; |
| | | |
| | | final TextEditingController _contentController = TextEditingController(); |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | } |
| | | |
| | | BoxDecoration getItemDecoration(Color bgColor, Color shadowColor) { |
| | | return BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.elliptical(10, 10)), |
| | | color: bgColor, |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | color: shadowColor, |
| | | blurRadius: 2.0, |
| | | offset: Offset(0.0, 5.0), //阴影y轴偏移量 |
| | | spreadRadius: 1 //阴影扩散程度 |
| | | ) |
| | | ]); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | resizeToAvoidBottomInset: false, |
| | | backgroundColor: Color(0xFFFFFFFF), |
| | | body: Container( |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | TopNavBar(title: "提意见"), |
| | | Container( |
| | | padding: const EdgeInsets.fromLTRB(17.5, 15, 17.5, 15), |
| | | decoration: BoxDecoration( |
| | | color: const Color(0xFFFAFAFA), |
| | | border: Border.all(color: Color(0xFFDBDBDB))), |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | children: [ |
| | | Wrap( |
| | | children: getQuestionTypes(), |
| | | ), |
| | | Container( |
| | | child: TextField( |
| | | controller: _contentController, |
| | | maxLines: 9, |
| | | maxLength: 200, |
| | | decoration: const InputDecoration( |
| | | focusedBorder: InputBorder.none, |
| | | border: InputBorder.none, |
| | | counterStyle: TextStyle(color: Color(0xFF666666)), |
| | | hintText: "请描述您要反馈的问题或意见", |
| | | hintStyle: TextStyle( |
| | | fontSize: 15, color: Color(0xFF999999))), |
| | | style: |
| | | TextStyle(color: Color(0xFF666666), fontSize: 15), |
| | | onChanged: (value) {}, |
| | | ), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | //按钮 |
| | | Container( |
| | | margin: EdgeInsets.fromLTRB(18, 50, 18, 0), |
| | | child: InkWell( |
| | | onTap: () { |
| | | var content = _contentController.text; |
| | | if (StringUtil.isNullOrEmpty(content)) { |
| | | ToastUtil.toast("请填写问题"); |
| | | return; |
| | | } |
| | | var type; |
| | | if (checkIndex > -1) { |
| | | type = questions[checkIndex]; |
| | | } |
| | | |
| | | FeedBackApiUtil.advice(context, type, content).then((value) { |
| | | if (value == null) { |
| | | return; |
| | | } |
| | | if (value["code"] == 0) { |
| | | Navigator.of(context).pop(); |
| | | } else { |
| | | ToastUtil.toast(value["msg"]); |
| | | } |
| | | }); |
| | | }, |
| | | child: Container( |
| | | height: 42.5, |
| | | alignment: Alignment.center, |
| | | decoration: const BoxDecoration( |
| | | color: Color(0xFF0E96FF), |
| | | borderRadius: BorderRadius.all(Radius.circular(10))), |
| | | child: const Text( |
| | | "提交反馈", |
| | | style: TextStyle(color: Colors.white, fontSize: 18), |
| | | ), |
| | | ), |
| | | ), |
| | | ) |
| | | ], |
| | | ), |
| | | )); |
| | | } |
| | | |
| | | int checkIndex = -1; |
| | | |
| | | List<Widget> getQuestionTypes() { |
| | | List<Widget> list = []; |
| | | |
| | | for (int i = 0; i < questions.length; i++) { |
| | | list.add(InkWell( |
| | | onTap: () { |
| | | if (checkIndex == i) { |
| | | setState(() { |
| | | checkIndex = -1; |
| | | }); |
| | | } else { |
| | | setState(() { |
| | | checkIndex = i; |
| | | }); |
| | | } |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.fromLTRB(10, 0, 10, 0), |
| | | margin: EdgeInsets.fromLTRB(0, 0, 17.5, 0), |
| | | height: 35, |
| | | width: 80, |
| | | decoration: BoxDecoration( |
| | | color: Colors.white, |
| | | borderRadius: BorderRadius.circular(17.5), |
| | | border: Border.all( |
| | | color: i == checkIndex |
| | | ? Color(0xFF0E96FF) |
| | | : Color(0xFFB4B4B4))), |
| | | child: Text( |
| | | questions[i], |
| | | style: TextStyle( |
| | | color: |
| | | i == checkIndex ? Color(0xFF0E96FF) : Color(0xFF666666), |
| | | fontSize: 14), |
| | | ), |
| | | ))); |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:convert'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; |
| | | import 'package:html/dom.dart' as dom; |
| | | import '../../api/http.dart'; |
| | | import '../../model/user/user_info.dart'; |
| | | import '../../ui/common/browser.dart'; |
| | | import '../../ui/widget/button.dart'; |
| | | import '../../utils/event_bus_util.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | import '../../utils/push_util.dart'; |
| | | import '../../utils/string_util.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | import '../../utils/ui_utils.dart'; |
| | | import '../../utils/user_util.dart'; |
| | | import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; |
| | | |
| | | void main() { |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: '登录', |
| | | theme: ThemeData(primaryColor: Color(0xFFF5F5F5)), |
| | | home: LoginPage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class LoginPage extends StatefulWidget { |
| | | //阿里云一键登录 |
| | | static const messageChannel = |
| | | BasicMessageChannel('AliyunPhoneNumberAuth', StandardMessageCodec()); |
| | | |
| | | LoginPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _LoginPageState createState() => _LoginPageState(); |
| | | } |
| | | |
| | | class _LoginPageState extends State<LoginPage> |
| | | with SingleTickerProviderStateMixin { |
| | | bool oneKeyLogin = false; |
| | | bool checked = false; |
| | | TextEditingController? phoneController = TextEditingController(); |
| | | TextEditingController? codeController = TextEditingController(); |
| | | String phone = ""; |
| | | String code = ""; |
| | | Timer? timer; |
| | | |
| | | //重新发送验证码倒计时 |
| | | int? reSendSMSTimeLeft; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | reSendSMSTimeLeft = -1; |
| | | //初始化微信登录监听 |
| | | fluwx.weChatResponseEventHandler.distinct((a, b) => a == b).listen((res) { |
| | | if (res is fluwx.WeChatAuthResponse) { |
| | | int errCode = res.errCode; |
| | | if (errCode == 0) { |
| | | String? code = res.code; |
| | | //TODO 把微信登录返回的code传给后台,剩下的事就交给后台处理 |
| | | } else if (errCode == -4) { |
| | | //showToast("用户拒绝授权"); |
| | | } else if (errCode == -2) { |
| | | // showToast("用户取消授权"); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | bool _aliyunLogin = false; |
| | | |
| | | void aliyunOneKeyLogin() async { |
| | | if (_aliyunLogin) { |
| | | return; |
| | | } |
| | | _aliyunLogin = true; |
| | | Future.delayed(const Duration(milliseconds: 1000), () { |
| | | _aliyunLogin = false; |
| | | }); |
| | | |
| | | showLoading(context); |
| | | |
| | | Map value = |
| | | await LoginPage.messageChannel.send({"method": "checkEnv"}) as Map; |
| | | dismissDialog(context); |
| | | if (value["code"] == 0) { |
| | | value = |
| | | await LoginPage.messageChannel.send({"method": "startLogin"}) as Map; |
| | | print("返回内容:${jsonEncode(value)}"); |
| | | if (value["code"] == 0) { |
| | | Map<String, dynamic>? resultValue = |
| | | await UserApiUtil.login(context, "", "", value["token"]); |
| | | |
| | | LoginPage.messageChannel.send({"method": "closeLogin"}); |
| | | |
| | | if (resultValue == null) return; |
| | | |
| | | if (resultValue["code"] == 0) { |
| | | UserInfo user = UserInfo.fromJson(resultValue["data"]); |
| | | _loginSuccess(user); |
| | | } else { |
| | | Fluttertoast.showToast(msg: value["msg"]); |
| | | } |
| | | } else if (value["code"] == 700000) { |
| | | //Fluttertoast.showToast(msg: "取消登录了"); |
| | | } |
| | | } else { |
| | | Fluttertoast.showToast(msg: value["msg"]); |
| | | setState(() { |
| | | oneKeyLogin = false; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | void qqLogin() async { |
| | | Map value = await UserUtil.loginQQ(); |
| | | } |
| | | |
| | | void _loginSuccess(UserInfo user) { |
| | | UserUtil.setUserInfo(user).then((value) { |
| | | print("登录成功"); |
| | | eventBus.fire(LoginEventBus(true)); |
| | | PushUtil.setAlias(user.id!.toString()).then((value) { |
| | | Navigator.pop(context); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | @override |
| | | void dispose() { |
| | | if (timer != null) { |
| | | timer!.cancel(); |
| | | } |
| | | super.dispose(); |
| | | } |
| | | |
| | | BoxDecoration getItemDecoration(Color bgColor, Color shadowColor) { |
| | | return BoxDecoration( |
| | | borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)), |
| | | color: bgColor, |
| | | boxShadow: [ |
| | | BoxShadow( |
| | | color: shadowColor, |
| | | blurRadius: 2.0, |
| | | offset: Offset(0.0, 5.0), //阴影y轴偏移量 |
| | | spreadRadius: 1 //阴影扩散程度 |
| | | ) |
| | | ]); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | resizeToAvoidBottomInset: false, |
| | | backgroundColor: Colors.white, |
| | | body: Stack( |
| | | children: [ |
| | | Column(children: [ |
| | | //登录内容区域 |
| | | Expanded( |
| | | child: SingleChildScrollView( |
| | | child: Padding( |
| | | padding: EdgeInsets.fromLTRB(40, 100, 40, 14), |
| | | child: Column( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/login/ic_login_logo.png", |
| | | width: 131, |
| | | ), |
| | | Container( |
| | | height: 70, |
| | | ), |
| | | Container( |
| | | constraints: BoxConstraints(minHeight: 200), |
| | | child: getLoginContent()), |
| | | Container( |
| | | height: 30, |
| | | ), |
| | | Text( |
| | | "其他方式登录", |
| | | style: TextStyle( |
| | | color: Color(0xFF666666), fontSize: 14), |
| | | ), |
| | | Container( |
| | | height: 21, |
| | | ), |
| | | Row( |
| | | mainAxisAlignment: |
| | | MainAxisAlignment.spaceAround, |
| | | children: [ |
| | | // getThirdLoginItem("微信登录", |
| | | // "assets/images/login/ic_login_wx.png"), |
| | | // getThirdLoginItem("QQ登录", |
| | | // "assets/images/login/ic_login_qq.png"), |
| | | oneKeyLogin |
| | | ? getThirdLoginItem("手机号登录", |
| | | "assets/imgs/login/ic_login_phone.png") |
| | | : getThirdLoginItem("一键登录", |
| | | "assets/imgs/login/ic_login_onekey.png"), |
| | | ], |
| | | ) |
| | | ])))), |
| | | //用户协议与隐私政策 |
| | | Row(children: [ |
| | | Container( |
| | | width: 25, |
| | | ), |
| | | RoundCheckBox( |
| | | value: checked, |
| | | onChanged: (value) { |
| | | setState(() { |
| | | checked = value; |
| | | }); |
| | | }, |
| | | ), |
| | | Expanded( |
| | | child: Container( |
| | | child: HtmlWidget( |
| | | "<p>登录即表明同意 <a href='${Constant.PROTOCOL_URL}'>用户协议</a> 和 <a href='${Constant.PRIVACY_URL}'>隐私政策</a> </p>", |
| | | textStyle: |
| | | const TextStyle(color: Color(0xFF999999)), |
| | | onTapUrl: (url) { |
| | | String? title = ""; |
| | | if (url == Constant.PROTOCOL_URL) { |
| | | title = "用户协议"; |
| | | } else { |
| | | title = "隐私政策"; |
| | | } |
| | | |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | BrowserPage( |
| | | title: title, |
| | | url: url, |
| | | ), |
| | | (data) {}); |
| | | |
| | | return true; |
| | | }))), |
| | | ]) |
| | | ]), |
| | | //关闭按钮 |
| | | Positioned( |
| | | top: 30, |
| | | left: 20, |
| | | child: InkWell( |
| | | onTap: () { |
| | | Navigator.of(context).pop(); |
| | | }, |
| | | child: Icon( |
| | | Icons.close, |
| | | size: 30, |
| | | ))) |
| | | ], |
| | | )); |
| | | } |
| | | |
| | | Widget getLoginContent() { |
| | | return oneKeyLogin |
| | | ? Container( |
| | | child: Column(children: [ |
| | | MyFillButton( |
| | | "本机号码一键登录", |
| | | 10, |
| | | height: 45, |
| | | fontSize: 17, |
| | | onClick: () { |
| | | aliyunOneKeyLogin(); |
| | | }, |
| | | ) |
| | | ])) |
| | | : Column( |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | children: [ |
| | | Container( |
| | | alignment: Alignment.centerLeft, |
| | | padding: EdgeInsets.fromLTRB(20, 0, 5, 0), |
| | | decoration: BoxDecoration( |
| | | color: const Color(0xFFF5F5F5), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Row( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/login/icon_phone.png", |
| | | width: 14, |
| | | height: 20, |
| | | ), |
| | | Container(width: 14), |
| | | Expanded( |
| | | child: TextField( |
| | | style: TextStyle(color: Color(0xFF333333), fontSize: 17), |
| | | onChanged: (value) { |
| | | setState(() { |
| | | phone = value; |
| | | }); |
| | | }, |
| | | textAlign: TextAlign.start, |
| | | keyboardType: TextInputType.phone, |
| | | controller: phoneController, |
| | | maxLength: 11, |
| | | decoration: InputDecoration( |
| | | counterText: "", |
| | | hintText: "请输入手机号", |
| | | hintStyle: |
| | | TextStyle(color: Color(0xFFCCCCCC), fontSize: 17), |
| | | contentPadding: EdgeInsets.only(bottom: 3), |
| | | border: InputBorder.none, |
| | | focusedBorder: InputBorder.none, |
| | | ), |
| | | )), |
| | | ], |
| | | ), |
| | | ), |
| | | Container(height: 10), |
| | | Container( |
| | | alignment: Alignment.centerLeft, |
| | | padding: EdgeInsets.fromLTRB(20, 0, 7, 0), |
| | | decoration: BoxDecoration( |
| | | color: const Color(0xFFF5F5F5), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Row( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/login/icon_code.png", |
| | | width: 16, |
| | | ), |
| | | Container(width: 14), |
| | | Expanded( |
| | | child: TextField( |
| | | style: TextStyle(color: Color(0xFF333333), fontSize: 17), |
| | | onChanged: (value) { |
| | | setState(() { |
| | | phone = value; |
| | | }); |
| | | }, |
| | | textAlign: TextAlign.start, |
| | | keyboardType: TextInputType.phone, |
| | | controller: codeController, |
| | | maxLength: 8, |
| | | decoration: const InputDecoration( |
| | | counterText: "", |
| | | hintText: "请输入验证码", |
| | | hintStyle: |
| | | TextStyle(color: Color(0xFFCCCCCC), fontSize: 17), |
| | | contentPadding: EdgeInsets.only(bottom: 3), |
| | | border: InputBorder.none, |
| | | focusedBorder: InputBorder.none, |
| | | ), |
| | | )), |
| | | MyFillButton( |
| | | (reSendSMSTimeLeft! > 0 |
| | | ? (reSendSMSTimeLeft.toString() + "S重新获取") |
| | | : reSendSMSTimeLeft == -1 |
| | | ? "获取验证码" |
| | | : "重新获取") |
| | | .toString(), |
| | | 10, |
| | | height: 34, |
| | | padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), |
| | | enable: (reSendSMSTimeLeft! < 1 && |
| | | StringUtil.isMobile(phoneController!.value.text)), |
| | | onClick: () { |
| | | if (!(reSendSMSTimeLeft! < 1 && |
| | | StringUtil.isMobile(phoneController!.value.text))) { |
| | | return; |
| | | } |
| | | //发送验证码 |
| | | UserApiUtil.sendSMS( |
| | | context, phoneController!.value.text) |
| | | .then((value) { |
| | | if (value != null && value["code"] == 0) { |
| | | setState(() { |
| | | reSendSMSTimeLeft = 60; |
| | | //倒计时 |
| | | timer = Timer.periodic(const Duration(seconds: 1), |
| | | (timer) { |
| | | if (reSendSMSTimeLeft! > 0) { |
| | | setState(() { |
| | | reSendSMSTimeLeft = reSendSMSTimeLeft! - 1; |
| | | }); |
| | | } else { |
| | | timer.cancel(); |
| | | } |
| | | }); |
| | | }); |
| | | } else { |
| | | ToastUtil.toast(value!["msg"]); |
| | | } |
| | | }); |
| | | }, |
| | | ), |
| | | ], |
| | | ), |
| | | ), |
| | | Container(height: 10), |
| | | const Text("未注册的手机号注册后系统会自动创建账户", |
| | | style: TextStyle(color: Color(0xFFA0A0A0), fontSize: 12)), |
| | | Container(height: 20), |
| | | MyFillButton( |
| | | "登录", |
| | | 10, |
| | | height: 45, |
| | | color: const Color(0xFFFF2B4B), |
| | | fontSize: 17, |
| | | enable: StringUtil.isMobile(phoneController!.value.text) && |
| | | codeController!.value.text.length >= 4, |
| | | onClick: () { |
| | | if (!(StringUtil.isMobile(phoneController!.value.text) && |
| | | codeController!.value.text.length >= 4)) { |
| | | return; |
| | | } |
| | | |
| | | if (!checked) { |
| | | Fluttertoast.showToast(msg: "请同意用户协议与隐私政策"); |
| | | return; |
| | | } |
| | | |
| | | UserApiUtil.login(context, phoneController!.value.text, |
| | | codeController!.value.text, "") |
| | | .then((value) { |
| | | print("结果: $value"); |
| | | if (value!["code"] == 0) { |
| | | UserInfo user = UserInfo.fromJson(value["data"]); |
| | | _loginSuccess(user); |
| | | } else { |
| | | Fluttertoast.showToast(msg: value["msg"]); |
| | | } |
| | | }); |
| | | }, |
| | | ), |
| | | ], |
| | | ); |
| | | } |
| | | |
| | | Widget getThirdLoginItem(String name, String iconAsset) { |
| | | return InkWell( |
| | | onTap: () { |
| | | if (name == "一键登录" || name == "手机号登录") { |
| | | setState(() { |
| | | oneKeyLogin = !oneKeyLogin; |
| | | }); |
| | | } else if (name == "QQ登录") { |
| | | qqLogin(); |
| | | } else if (name == "微信登录") { |
| | | UserUtil.loginWX(); |
| | | } |
| | | }, |
| | | child: Container( |
| | | constraints: BoxConstraints(minWidth: 80), |
| | | child: Column( |
| | | children: [ |
| | | Image.asset( |
| | | iconAsset, |
| | | height: 49, |
| | | ), |
| | | Container( |
| | | height: 8, |
| | | ), |
| | | Text( |
| | | name, |
| | | style: const TextStyle(color: Color(0xFF9DAAB3), fontSize: 12), |
| | | ) |
| | | ], |
| | | )), |
| | | ); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import '../../api/http.dart'; |
| | | import '../../ui/common/browser.dart'; |
| | | import '../../ui/widget/dialog.dart'; |
| | | import '../../ui/widget/nav.dart'; |
| | | import '../../utils/cache_util.dart'; |
| | | import '../../utils/config_util.dart'; |
| | | import '../../utils/event_bus_util.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | import '../../utils/push_util.dart'; |
| | | import '../../utils/setting_util.dart'; |
| | | import '../../utils/string_util.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | import '../../utils/ui_utils.dart'; |
| | | import '../../utils/user_util.dart'; |
| | | import 'package:package_info/package_info.dart'; |
| | | |
| | | void main() { |
| | | runApp(MyApp()); |
| | | } |
| | | |
| | | class MyApp extends StatelessWidget { |
| | | // This widget is the root of your application. |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return MaterialApp( |
| | | title: '设置', |
| | | theme: ThemeData(primaryColor: const Color(0xFFF5F5F5)), |
| | | home: SettingPage(title: ''), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class SettingPage extends StatefulWidget { |
| | | SettingPage({Key? key, required this.title}) : super(key: key); |
| | | |
| | | // This widget is the home page of your application. It is stateful, meaning |
| | | // that it has a State object (defined below) that contains fields that affect |
| | | // how it looks. |
| | | |
| | | // This class is the configuration for the state. It holds the values (in this |
| | | // case the title) provided by the parent (in this case the App widget) and |
| | | // used by the build method of the State. Fields in a Widget subclass are |
| | | // always marked "final". |
| | | |
| | | final String title; |
| | | |
| | | @override |
| | | _SettingPageState createState() => _SettingPageState(); |
| | | } |
| | | |
| | | class _SettingPageState extends State<SettingPage> |
| | | with SingleTickerProviderStateMixin { |
| | | bool msg = false; |
| | | bool ad = false; |
| | | bool login = false; |
| | | |
| | | String cacheSize = "0B"; |
| | | String version = ""; |
| | | |
| | | @override |
| | | void initState() { |
| | | super.initState(); |
| | | UserUtil.isLogin().then((value) { |
| | | setState(() { |
| | | login = value; |
| | | }); |
| | | }); |
| | | |
| | | _getCacheSize(); |
| | | _getVersion(); |
| | | |
| | | SettingUtil.isEnablePush().then((value) { |
| | | setState(() { |
| | | msg = value; |
| | | }); |
| | | }); |
| | | |
| | | SettingUtil.isEnableRecommendAd().then((value) { |
| | | ad = value; |
| | | }); |
| | | } |
| | | |
| | | ///获取缓存大小 |
| | | void _getCacheSize() async { |
| | | int byteSize = await CacheUtil.total(); |
| | | String? desc; |
| | | if (byteSize < 1000) { |
| | | desc = byteSize.toString() + "KB"; |
| | | } else if (byteSize < 1000 * 1000) { |
| | | desc = (byteSize / 1000).toStringAsFixed(0) + "KB"; |
| | | } else if (byteSize < 1000 * 1000 * 1000) { |
| | | desc = (byteSize / (1000 * 1000)).toStringAsFixed(1) + "MB"; |
| | | } else { |
| | | desc = (byteSize / (1000 * 1000 * 1000)).toStringAsFixed(1) + "GB"; |
| | | } |
| | | |
| | | setState(() { |
| | | cacheSize = desc!; |
| | | }); |
| | | } |
| | | |
| | | void _getVersion() async { |
| | | PackageInfo packageInfo = await PackageInfo.fromPlatform(); |
| | | setState(() { |
| | | version = packageInfo.version; |
| | | }); |
| | | } |
| | | |
| | | Future logout() async { |
| | | var uid = await UserUtil.getUid(); |
| | | Map<String, dynamic>? map = await UserApiUtil.logout(context, uid); |
| | | if (map!["code"] == 0) { |
| | | UserUtil.logout(); |
| | | setState(() { |
| | | login = false; |
| | | }); |
| | | ToastUtil.toast("退出成功"); |
| | | Navigator.of(context).pop(); |
| | | } else { |
| | | ToastUtil.toast(map["msg"]); |
| | | } |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Scaffold( |
| | | backgroundColor: const Color(0xFFF5F5F5), |
| | | body: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | TopNavBar(title: "设置"), |
| | | getBigItemView( |
| | | title: "推送免打扰", |
| | | content: "关闭后,21:00-09:00不接受任何推送", |
| | | marginTop: 14, |
| | | marginBottom: 1, |
| | | checked: msg, |
| | | changed: (bool value) { |
| | | SettingUtil.setPush(value).then((value1) { |
| | | setState(() { |
| | | msg = value; |
| | | }); |
| | | }); |
| | | }), |
| | | getBigItemView( |
| | | title: "个性化广告推荐", |
| | | content: "关闭后,广告数量将不变,但内容相关度会降低", |
| | | marginTop: 0, |
| | | marginBottom: 16, |
| | | checked: ad, |
| | | changed: (bool value) { |
| | | SettingUtil.setRecommendAd(value).then((value1) { |
| | | setState(() { |
| | | ad = value; |
| | | }); |
| | | }); |
| | | }), |
| | | getCommonItemView( |
| | | title: "清理缓存", |
| | | content: cacheSize, |
| | | onClick: () { |
| | | DialogUtil.showDialog( |
| | | context, |
| | | NotifyDialog("温馨提示", "是否清楚缓存?", () {}, () { |
| | | CacheUtil.clear().then((value) { |
| | | ToastUtil.toast("缓存清除成功"); |
| | | _getCacheSize(); |
| | | }); |
| | | })); |
| | | }), |
| | | getCommonItemView( |
| | | title: "检查更新", |
| | | content: "版本号:$version", |
| | | onClick: () { |
| | | ToastUtil.toast("已经是最新版本"); |
| | | }), |
| | | getCommonItemView( |
| | | title: "账户注销", |
| | | content: "", |
| | | onClick: () { |
| | | ConfigUtil.getConfig(ConfigKey.unRegister).then((value) { |
| | | if (!StringUtil.isNullOrEmpty(value)) { |
| | | NavigatorUtil.navigateToNextPage(context, |
| | | BrowserPage(title: "账户注销", url: value!), (data) {}); |
| | | } |
| | | }); |
| | | }), |
| | | getCommonItemView( |
| | | title: "隐私投诉", |
| | | content: "", |
| | | onClick: () { |
| | | ConfigUtil.getConfig(ConfigKey.privacyComplain).then((value) { |
| | | if (!StringUtil.isNullOrEmpty(value)) { |
| | | NavigatorUtil.navigateToNextPage(context, |
| | | BrowserPage(title: "隐私投诉", url: value!), (data) {}); |
| | | } |
| | | }); |
| | | }), |
| | | // getCommonItemView( |
| | | // title: "第三方SDK列表", |
| | | // content: "", |
| | | // onClick: () { |
| | | // |
| | | // ConfigUtil.getConfig(ConfigKey.sdkList).then((value) { |
| | | // if (!StringUtil.isNullOrEmpty(value)) { |
| | | // NavigatorUtil.navigateToNextPage( |
| | | // context, BrowserPage(title: "第三方SDK列表", url: value!), (data) {}); |
| | | // } |
| | | // }); |
| | | // }), |
| | | Expanded( |
| | | child: Container(), |
| | | ), |
| | | login |
| | | ? Container( |
| | | child: Stack( |
| | | children: [ |
| | | InkWell( |
| | | onTap: () { |
| | | print("退出登录"); |
| | | logout(); |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | height: 48, |
| | | color: Colors.white, |
| | | child: const Text( |
| | | "退出登录", |
| | | style: TextStyle( |
| | | color: ColorConstant.theme, fontSize: 16), |
| | | ))) |
| | | ], |
| | | )) |
| | | : Container(), |
| | | ], |
| | | )); |
| | | } |
| | | |
| | | Widget getCommonItemView( |
| | | {required String title, |
| | | String content = "", |
| | | required GestureTapCallback onClick}) { |
| | | return Container( |
| | | height: 53, |
| | | margin: const EdgeInsets.fromLTRB(0, 0, 0, 1), |
| | | color: Colors.white, |
| | | child: InkWell( |
| | | onTap: () { |
| | | onClick(); |
| | | }, |
| | | child: Container( |
| | | padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), |
| | | child: Flex( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Text( |
| | | title, |
| | | style: |
| | | const TextStyle(fontSize: 16, color: Color(0xFF333333)), |
| | | ), |
| | | Expanded( |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | mainAxisAlignment: MainAxisAlignment.end, |
| | | children: [ |
| | | Container( |
| | | child: Text(content, |
| | | style: const TextStyle( |
| | | fontSize: 14, color: Color(0xFF959595))), |
| | | margin: const EdgeInsets.fromLTRB(0, 0, 13.5, 0), |
| | | ), |
| | | Image.asset( |
| | | "assets/imgs/common/icon_array_right.png", |
| | | height: 13.5, |
| | | ) |
| | | ], |
| | | )) |
| | | ], |
| | | )), |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | Widget getBigItemView( |
| | | {required String title, |
| | | String content = "", |
| | | bool checked = false, |
| | | required ValueChanged<bool> changed, |
| | | double marginTop = 0, |
| | | double marginBottom = 0}) { |
| | | return Container( |
| | | height: 68, |
| | | margin: EdgeInsets.fromLTRB(0, marginTop, 0, marginBottom), |
| | | color: Colors.white, |
| | | child: Container( |
| | | padding: const EdgeInsets.fromLTRB(20, 0, 20, 0), |
| | | child: Stack(children: [ |
| | | Flex( |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Text( |
| | | title, |
| | | style: TextStyle(fontSize: 16, color: Color(0xFF333333)), |
| | | ), |
| | | Container( |
| | | child: Text(content, |
| | | style: const TextStyle( |
| | | fontSize: 9, color: Color(0xFF959595))), |
| | | margin: const EdgeInsets.fromLTRB(0, 5, 0, 0), |
| | | ) |
| | | ], |
| | | ), |
| | | Container(), |
| | | Positioned( |
| | | right: 0, |
| | | top: 0, |
| | | bottom: 0, |
| | | child: InkWell( |
| | | onTap: () { |
| | | changed(!checked); |
| | | }, |
| | | child: Image.asset( |
| | | checked |
| | | ? "assets/imgs/common/icon_check_true.png" |
| | | : "assets/imgs/common/icon_check_false.png", |
| | | height: 30, |
| | | width: 60, |
| | | ))) |
| | | ])), |
| | | ); |
| | | } |
| | | } |
New file |
| | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:pull_to_refresh/pull_to_refresh.dart'; |
| | | |
| | | WaterDropHeader refreshHeader = const WaterDropHeader(complete: Text("刷新成功")); |
| | | |
| | | CustomFooter loadFotter = CustomFooter( |
| | | builder: (BuildContext context, LoadStatus? mode) { |
| | | Widget body; |
| | | if (mode == LoadStatus.idle) { |
| | | body = Text("上拉加载"); |
| | | } else if (mode == LoadStatus.loading) { |
| | | body = CupertinoActivityIndicator(); |
| | | } else if (mode == LoadStatus.failed) { |
| | | body = Text("加载失败!点击重试!"); |
| | | } else if (mode == LoadStatus.canLoading) { |
| | | body = Text("松手,加载更多!"); |
| | | } else { |
| | | body = Text("没有更多数据了!"); |
| | | } |
| | | return Container( |
| | | height: 55.0, |
| | | child: Center(child: body), |
| | | ); |
| | | }, |
| | | ); |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/material.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | |
| | | class MyOutlineButton extends StatelessWidget { |
| | | final String text; |
| | | final double radius; |
| | | final double height; |
| | | final double? width; |
| | | final Color color; |
| | | final double fontSize; |
| | | final GestureTapCallback? onClick; |
| | | final EdgeInsets? padding; |
| | | |
| | | MyOutlineButton(this.text, this.radius, |
| | | {GestureTapCallback? this.onClick, |
| | | Color this.color = ColorConstant.theme, |
| | | double this.height = 26, |
| | | double this.fontSize = 12, |
| | | double? this.width = null, |
| | | EdgeInsets? this.padding = null}); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | Container child = Container( |
| | | alignment: Alignment.center, |
| | | height: height, |
| | | width: width, |
| | | padding: padding, |
| | | decoration: BoxDecoration( |
| | | color: Colors.transparent, |
| | | border: Border.all(color: color, width: 1), |
| | | borderRadius: BorderRadius.circular(radius), |
| | | ), |
| | | child: Text( |
| | | text, |
| | | style: TextStyle(color: color, fontSize: fontSize), |
| | | ), |
| | | ); |
| | | |
| | | return InkWell( |
| | | onTap: () { |
| | | onClick!(); |
| | | }, |
| | | child: child); |
| | | } |
| | | } |
| | | |
| | | class MyFillButton extends StatelessWidget { |
| | | final String text; |
| | | final Color textColor; |
| | | final double radius; |
| | | final double height; |
| | | final double? width; |
| | | final Color color; |
| | | final double fontSize; |
| | | final GestureTapCallback? onClick; |
| | | final EdgeInsets? padding; |
| | | final bool? enable; |
| | | |
| | | MyFillButton(this.text, this.radius, |
| | | {GestureTapCallback? this.onClick, |
| | | Color this.color = ColorConstant.theme, |
| | | Color this.textColor = Colors.white, |
| | | double this.height = 26, |
| | | double this.fontSize = 12, |
| | | double? this.width = null, |
| | | EdgeInsets? this.padding = null, |
| | | bool? this.enable = true}); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | Container child = Container( |
| | | alignment: Alignment.center, |
| | | height: height, |
| | | width: width, |
| | | padding: padding, |
| | | decoration: BoxDecoration( |
| | | color: enable! ? color : const Color(0xFFCBCBCB), |
| | | borderRadius: BorderRadius.circular(radius), |
| | | ), |
| | | child: Text( |
| | | text, |
| | | style: TextStyle(color: textColor, fontSize: fontSize), |
| | | ), |
| | | ); |
| | | |
| | | return InkWell( |
| | | onTap: () { |
| | | onClick!(); |
| | | }, |
| | | child: child); |
| | | } |
| | | } |
| | | |
| | | class RoundCheckBox extends StatefulWidget { |
| | | var value = false; |
| | | |
| | | Function(bool) onChanged; |
| | | |
| | | RoundCheckBox({Key? key, required this.value, required this.onChanged}) |
| | | : super(key: key); |
| | | |
| | | @override |
| | | _RoundCheckBoxState createState() => _RoundCheckBoxState(); |
| | | } |
| | | |
| | | class _RoundCheckBoxState extends State<RoundCheckBox> { |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Center( |
| | | child: GestureDetector( |
| | | onTap: () { |
| | | widget.value = !widget.value; |
| | | widget.onChanged(widget.value); |
| | | }, |
| | | child: Padding( |
| | | padding: const EdgeInsets.all(10.0), |
| | | child: widget.value |
| | | ? const Icon( |
| | | Icons.check_circle, |
| | | size: 19, |
| | | color: Colors.green, |
| | | ) |
| | | : const Icon( |
| | | Icons.panorama_fish_eye, |
| | | size: 19, |
| | | color: Colors.black12, |
| | | ), |
| | | )), |
| | | ); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | import 'dart:typed_data'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/rendering.dart'; |
| | | |
| | | ///对widget截图 |
| | | |
| | | class CaptureWidget extends StatelessWidget { |
| | | //截图组件 |
| | | GlobalKey rootWidgetKey = GlobalKey(); |
| | | final Widget widget; |
| | | final CaptureController captureController; |
| | | |
| | | CaptureWidget({required this.widget, required this.captureController}) { |
| | | captureController.setGlobalKey(rootWidgetKey); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return RepaintBoundary(key: rootWidgetKey, child: widget); |
| | | } |
| | | } |
| | | |
| | | class CaptureController { |
| | | GlobalKey? _globalKey; |
| | | |
| | | setGlobalKey(GlobalKey globalKey) { |
| | | _globalKey = globalKey; |
| | | } |
| | | |
| | | Future<String> capturePng() async { |
| | | try { |
| | | RenderRepaintBoundary? boundary = _globalKey!.currentContext! |
| | | .findRenderObject() as RenderRepaintBoundary; |
| | | var image = await boundary.toImage(pixelRatio: 3.0); |
| | | ByteData? byteData = await image.toByteData(format: ImageByteFormat.png); |
| | | Uint8List pngBytes = byteData!.buffer.asUint8List(); |
| | | String str = base64.encode(pngBytes); |
| | | return str; |
| | | } catch (e) {} |
| | | return ""; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter_spinkit/flutter_spinkit.dart'; |
| | | import 'package:html/dom.dart' as dom; |
| | | import '../../ui/common/browser.dart'; |
| | | import '../../utils/pageutils.dart'; |
| | | import '../../utils/ui_constant.dart'; |
| | | import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; |
| | | |
| | | //通用弹框 |
| | | class NotifyDialog extends Dialog { |
| | | BuildContext? context; |
| | | final String title; |
| | | final String content; |
| | | final GestureTapCallback onCancel; |
| | | final GestureTapCallback onSure; |
| | | final bool richText; |
| | | final double fontSize; |
| | | final double height; |
| | | final Color contentColor; |
| | | bool touchOutCancel = false; |
| | | final String cancelName; |
| | | final String sureName; |
| | | |
| | | NotifyDialog(this.title, this.content, this.onCancel, this.onSure, |
| | | {this.fontSize = 16.0, |
| | | this.richText = false, |
| | | this.height = 240, |
| | | this.contentColor = const Color(0xFF7E7E7E), |
| | | this.cancelName = "取消", |
| | | this.sureName = "确定"}); |
| | | |
| | | Widget getContent(BuildContext context) { |
| | | if (richText) { |
| | | return SingleChildScrollView( |
| | | child: HtmlWidget(content, onTapUrl: (String url) { |
| | | NavigatorUtil.navigateToNextPage( |
| | | context, |
| | | BrowserPage( |
| | | title: "", |
| | | url: url, |
| | | ), |
| | | (data) {}); |
| | | |
| | | return true; |
| | | })); |
| | | } else { |
| | | return Text( |
| | | content, |
| | | style: TextStyle(color: contentColor, fontSize: fontSize), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | Offset? offset; |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | double width = MediaQuery.of(context).size.width; |
| | | double dialogWidth = width * 4 / 5; |
| | | print("屏幕宽:$width"); |
| | | |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Container( |
| | | decoration: const BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.circular(15)), |
| | | color: Colors.white), |
| | | alignment: Alignment.topCenter, |
| | | height: height, |
| | | width: dialogWidth, |
| | | child: Flex( |
| | | mainAxisAlignment: MainAxisAlignment.start, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | //-------标题区域-------- |
| | | Container( |
| | | alignment: Alignment.center, |
| | | height: 60, |
| | | child: Text( |
| | | title, |
| | | style: TextStyle(fontSize: 18, color: Colors.white), |
| | | ), |
| | | decoration: const BoxDecoration( |
| | | color: Color(0xFF1CC7FF), |
| | | borderRadius: BorderRadius.only( |
| | | topLeft: Radius.circular(15), |
| | | topRight: Radius.circular(15)), |
| | | )), |
| | | //-------内容区域-------- |
| | | Expanded( |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: const EdgeInsets.fromLTRB(15, 5, 15, 5), |
| | | child: getContent(context), |
| | | )), |
| | | |
| | | //------按钮区域-------- |
| | | Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | Navigator.pop(context); |
| | | onCancel(); |
| | | }, |
| | | child: Container( |
| | | margin: EdgeInsets.fromLTRB(15, 0, 6, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | border: Border.all(color: Color(0xFF0E96FF)), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | cancelName, |
| | | style: const TextStyle( |
| | | color: Color(0xFF0E96FF), fontSize: 18), |
| | | ), |
| | | ), |
| | | )), |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | Navigator.pop(context); |
| | | onSure(); |
| | | }, |
| | | child: Container( |
| | | margin: const EdgeInsets.fromLTRB(6, 0, 15, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | color: Color(0xFF0E96FF), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | sureName, |
| | | style: const TextStyle( |
| | | color: Colors.white, fontSize: 18), |
| | | ), |
| | | ), |
| | | )) |
| | | ], |
| | | ) |
| | | ], |
| | | ), |
| | | )))); |
| | | } |
| | | } |
| | | |
| | | ///权限弹框 |
| | | class PermissionNotifyDialog extends Dialog { |
| | | final GestureTapCallback onOpen; |
| | | |
| | | PermissionNotifyDialog(this.onOpen); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | double width = MediaQuery.of(context).size.width; |
| | | double dialogWidth = width * 4 / 5; |
| | | print("屏幕宽:$width"); |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Container( |
| | | width: dialogWidth, |
| | | child: Flex( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/common/ic_permission_notify_top.png"), |
| | | Container( |
| | | padding: EdgeInsets.all(16), |
| | | decoration: BoxDecoration( |
| | | borderRadius: BorderRadius.only( |
| | | bottomLeft: Radius.circular(15), |
| | | bottomRight: Radius.circular(15)), |
| | | color: Colors.white), |
| | | child: Flex( |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | getPermissionItem( |
| | | title: "手机", |
| | | content: "校验手机识别码,防止账号被盗", |
| | | icon: Image.asset( |
| | | "assets/imgs/common/icon_permission_notify_phone.png", |
| | | width: 21, |
| | | )), |
| | | Container( |
| | | height: 30, |
| | | ), |
| | | getPermissionItem( |
| | | title: "存储", |
| | | content: "缓存图片和视频,降低流量消耗", |
| | | icon: Image.asset( |
| | | "assets/imgs/common/icon_permission_notify_save.png", |
| | | width: 26, |
| | | )), |
| | | Container( |
| | | height: 30, |
| | | ), |
| | | getPermissionItem( |
| | | title: "位置", |
| | | content: "定位用户", |
| | | icon: Image.asset( |
| | | "assets/imgs/common/icon_permission_notify_location.png", |
| | | width: 26, |
| | | )), |
| | | Container( |
| | | height: 36, |
| | | ), |
| | | InkWell( |
| | | onTap: () { |
| | | onOpen(); |
| | | }, |
| | | child: Container( |
| | | height: 44, |
| | | alignment: Alignment.center, |
| | | decoration: BoxDecoration( |
| | | borderRadius: BorderRadius.circular(10), |
| | | color: const Color(0xFF0E96FF)), |
| | | child: const Text( |
| | | "立即开启", |
| | | style: TextStyle( |
| | | fontSize: 18, color: Colors.white), |
| | | ), |
| | | ), |
| | | ) |
| | | ], |
| | | ), |
| | | ), |
| | | ], |
| | | ))))); |
| | | } |
| | | |
| | | //权限项 |
| | | Widget getPermissionItem( |
| | | {required Image icon, required String title, required String content}) { |
| | | return Flex( |
| | | direction: Axis.horizontal, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | width: 34, |
| | | ), |
| | | icon, |
| | | Container( |
| | | width: 4, |
| | | ), |
| | | Expanded( |
| | | child: Flex( |
| | | crossAxisAlignment: CrossAxisAlignment.start, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | Text(title, |
| | | style: TextStyle(fontSize: 17, color: Color(0xFF6B6B6B))), |
| | | Text(content, |
| | | style: TextStyle(fontSize: 12, color: Color(0xFFA0A0A0)), |
| | | softWrap: false, |
| | | overflow: TextOverflow.ellipsis) |
| | | ], |
| | | )) |
| | | ], |
| | | ); |
| | | } |
| | | } |
| | | |
| | | ///邀请定位 |
| | | class RequireLocationDialog extends Dialog { |
| | | BuildContext? context; |
| | | final String phone; |
| | | final GestureTapCallback onCancel; |
| | | final GestureTapCallback onSure; |
| | | |
| | | RequireLocationDialog(this.phone, this.onCancel, this.onSure); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | double width = MediaQuery.of(context).size.width; |
| | | double dialogWidth = width * 4 / 5; |
| | | print("屏幕宽:$width"); |
| | | |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Container( |
| | | decoration: const BoxDecoration( |
| | | borderRadius: BorderRadius.all(Radius.circular(15)), |
| | | color: Colors.white), |
| | | alignment: Alignment.topCenter, |
| | | height: 380, |
| | | width: dialogWidth, |
| | | child: Flex( |
| | | mainAxisAlignment: MainAxisAlignment.start, |
| | | direction: Axis.vertical, |
| | | children: [ |
| | | //-------标题区域-------- |
| | | Image.asset( |
| | | "assets/imgs/common/ic_require_location_top.png"), |
| | | //-------内容区域-------- |
| | | Expanded( |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: EdgeInsets.fromLTRB(15, 5, 15, 5), |
| | | child: Column( |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | height: 15, |
| | | ), |
| | | const Text( |
| | | "位置共享授权", |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), fontSize: 17), |
| | | ), |
| | | Container( |
| | | height: 49, |
| | | ), |
| | | Row( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Image.asset( |
| | | "assets/imgs/common/icon_require_location_phone.png", |
| | | height: 15, |
| | | ), |
| | | Container( |
| | | width: 10, |
| | | ), |
| | | Text( |
| | | phone, |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), |
| | | fontSize: 18), |
| | | ), |
| | | ], |
| | | ), |
| | | Container( |
| | | height: 10, |
| | | ), |
| | | const Text( |
| | | "该手机号用户请求与你进行位置共享。", |
| | | style: TextStyle( |
| | | color: Color(0xFF666666), fontSize: 15), |
| | | ), |
| | | Container( |
| | | height: 10, |
| | | ), |
| | | const Text( |
| | | "温馨提醒:你同意后可在定位人列表中删除", |
| | | style: TextStyle( |
| | | color: Color(0xFFA0A0A0), fontSize: 12), |
| | | ), |
| | | ], |
| | | ))), |
| | | |
| | | //------按钮区域-------- |
| | | Flex( |
| | | direction: Axis.horizontal, |
| | | children: [ |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | onCancel(); |
| | | }, |
| | | child: Container( |
| | | margin: EdgeInsets.fromLTRB(15, 0, 6, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | border: Border.all(color: Color(0xFF0E96FF)), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | "不同意", |
| | | style: TextStyle( |
| | | color: Color(0xFF0E96FF), fontSize: 18), |
| | | ), |
| | | ), |
| | | )), |
| | | Expanded( |
| | | child: InkWell( |
| | | onTap: () { |
| | | onSure(); |
| | | }, |
| | | child: Container( |
| | | margin: EdgeInsets.fromLTRB(6, 0, 15, 15), |
| | | alignment: Alignment.center, |
| | | height: 44, |
| | | decoration: BoxDecoration( |
| | | color: Color(0xFF0E96FF), |
| | | borderRadius: BorderRadius.circular(10)), |
| | | child: Text( |
| | | "同意", |
| | | style: TextStyle( |
| | | color: Colors.white, fontSize: 18), |
| | | ), |
| | | ), |
| | | )) |
| | | ], |
| | | ) |
| | | ], |
| | | ), |
| | | )))); |
| | | } |
| | | } |
| | | |
| | | ///ListView弹框 |
| | | class ListViewDialog extends Dialog { |
| | | BuildContext? context; |
| | | final ListView listView; |
| | | final GestureTapCallback onClose; |
| | | final double maxHeight; |
| | | final double? dwidth; |
| | | |
| | | ListViewDialog(this.listView, this.onClose, |
| | | {this.maxHeight = 420, this.dwidth}); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | double swidth = MediaQuery.of(context).size.width; |
| | | |
| | | double dialogWidth = swidth - 20; |
| | | print("屏幕宽:$swidth"); |
| | | if (dwidth != null) { |
| | | dialogWidth = dwidth!; |
| | | } |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Column( |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | mainAxisSize: MainAxisSize.min, |
| | | children: [ |
| | | ClipRRect( |
| | | borderRadius: BorderRadius.circular(10), |
| | | child: Container( |
| | | constraints: BoxConstraints(maxHeight: maxHeight), |
| | | color: Colors.white, |
| | | alignment: Alignment.topCenter, |
| | | width: dialogWidth, |
| | | child: listView, |
| | | )), |
| | | Container( |
| | | height: 20, |
| | | ), |
| | | InkWell( |
| | | child: Image.asset( |
| | | "assets/imgs/common/icon_dialog_close.png", |
| | | height: 32, |
| | | width: 32, |
| | | ), |
| | | onTap: () { |
| | | onClose(); |
| | | }, |
| | | ), |
| | | ])))); |
| | | } |
| | | } |
| | | |
| | | ///ListView弹框 |
| | | class LoadingDialog extends Dialog { |
| | | BuildContext? context; |
| | | final String? text; |
| | | |
| | | LoadingDialog(this.text); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: const Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: SpinKitCircle( |
| | | color: ColorConstant.theme, |
| | | size: 80.0, |
| | | )))); |
| | | } |
| | | } |
| | | |
| | | class CustomDialog extends Dialog { |
| | | BuildContext? context; |
| | | final Widget contentWidget; |
| | | |
| | | CustomDialog(this.contentWidget); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | this.context = context; |
| | | //关闭弹框 |
| | | // Navigator.pop(context); |
| | | return WillPopScope( |
| | | onWillPop: () async { |
| | | return false; |
| | | }, |
| | | child: Material( |
| | | type: MaterialType.transparency, |
| | | child: Align( |
| | | alignment: Alignment.center, |
| | | child: Column( |
| | | mainAxisSize: MainAxisSize.min, |
| | | crossAxisAlignment: CrossAxisAlignment.center, |
| | | children: [ |
| | | contentWidget, |
| | | Container( |
| | | height: 20, |
| | | ), |
| | | InkWell( |
| | | onTap: () { |
| | | Navigator.of(context).pop(); |
| | | }, |
| | | child: Image.asset( |
| | | "assets/imgs/common/icon_dialog_close.png", |
| | | height: 32, |
| | | width: 32, |
| | | )) |
| | | ], |
| | | )))); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | |
| | | class TopNavBar extends StatelessWidget { |
| | | final String title; |
| | | GestureTapCallback? back; |
| | | String? rightText; |
| | | Widget? rightIcon; |
| | | GestureTapCallback? rightClick; |
| | | final Color textColor; |
| | | final Color backGround; |
| | | final Image backIcon; |
| | | |
| | | TopNavBar( |
| | | {required this.title, |
| | | GestureTapCallback? this.back, |
| | | String? this.rightText, |
| | | Widget? this.rightIcon, |
| | | GestureTapCallback? this.rightClick, |
| | | Color this.textColor = const Color(0xFF333333), |
| | | Color this.backGround = Colors.white, |
| | | Image this.backIcon = const Image( |
| | | image: AssetImage( |
| | | "assets/imgs/common/icon_back.png", |
| | | ), |
| | | height: 19)}); |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return Flex(direction: Axis.vertical, children: [ |
| | | Container( |
| | | height: MediaQuery.of(context).viewPadding.top, |
| | | color: backGround, |
| | | ), |
| | | Container( |
| | | color: backGround, |
| | | height: 48, |
| | | child: Stack( |
| | | alignment: Alignment.centerLeft, |
| | | children: [ |
| | | Positioned( |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | child: Flex( |
| | | direction: Axis.horizontal, |
| | | mainAxisAlignment: MainAxisAlignment.center, |
| | | children: [ |
| | | Container( |
| | | width: 50, |
| | | ), |
| | | Expanded( |
| | | child: Center( |
| | | child: Text( |
| | | title, |
| | | maxLines: 1, |
| | | overflow: TextOverflow.ellipsis, |
| | | style: TextStyle(fontSize: 18, color: textColor), |
| | | ))), |
| | | Container( |
| | | width: 50, |
| | | ) |
| | | ], |
| | | ))), |
| | | ((rightText != null && rightText!.isNotEmpty) || rightIcon != null) |
| | | ? Positioned( |
| | | right: 0, |
| | | top: 0, |
| | | bottom: 0, |
| | | child: InkWell( |
| | | onTap: () { |
| | | rightClick!(); |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | padding: const EdgeInsets.only(right: 10), |
| | | child: rightIcon ?? Text( |
| | | rightText!, |
| | | style: |
| | | TextStyle(fontSize: 15, color: textColor), |
| | | ), |
| | | ))) |
| | | : Container(), |
| | | InkWell( |
| | | onTap: () { |
| | | if (back != null) { |
| | | back!(); |
| | | } else { |
| | | Navigator.pop(context); |
| | | } |
| | | }, |
| | | child: Container( |
| | | alignment: Alignment.center, |
| | | width: 42, |
| | | height: 48, |
| | | child: backIcon, |
| | | )) |
| | | ], |
| | | ), |
| | | ) |
| | | ]); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:math'; |
| | | import 'dart:ui' as ui; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | |
| | | ///SOS雷达扫描View |
| | | class RadarView extends StatefulWidget { |
| | | @override |
| | | _RadarViewState createState() => _RadarViewState(); |
| | | } |
| | | |
| | | class _RadarViewState extends State<RadarView> |
| | | with SingleTickerProviderStateMixin { |
| | | AnimationController? _controller; |
| | | Animation<double>? _animation; |
| | | |
| | | @override |
| | | void initState() { |
| | | _controller = |
| | | AnimationController(vsync: this, duration: Duration(seconds: 2)); |
| | | _animation = Tween(begin: .0, end: pi * 2).animate(_controller!); |
| | | _controller!.repeat(); |
| | | super.initState(); |
| | | } |
| | | |
| | | @override |
| | | void dispose() { |
| | | _controller!.dispose(); |
| | | super.dispose(); |
| | | } |
| | | |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | return AnimatedBuilder( |
| | | animation: _animation!, |
| | | builder: (context, child) { |
| | | return CustomPaint( |
| | | painter: RadarPainter(_animation!.value), |
| | | ); |
| | | }, |
| | | ); |
| | | } |
| | | } |
| | | |
| | | ///SOS雷达扫描动画 |
| | | class RadarPainter extends CustomPainter { |
| | | final double angle; |
| | | |
| | | final Paint _bgPaint = Paint() |
| | | ..color = Colors.white |
| | | ..strokeWidth = 1 |
| | | ..style = PaintingStyle.stroke; |
| | | |
| | | final Paint _paint = Paint()..style = PaintingStyle.fill; |
| | | |
| | | int circleCount = 0; |
| | | |
| | | RadarPainter(this.angle); |
| | | |
| | | @override |
| | | void paint(Canvas canvas, Size size) { |
| | | var radius = min(size.width / 2, size.height / 2); |
| | | |
| | | // canvas.drawLine(Offset(size.width / 2, size.height / 2 - radius), |
| | | // Offset(size.width / 2, size.height / 2 + radius), _bgPaint); |
| | | // canvas.drawLine(Offset(size.width / 2 - radius, size.height / 2), |
| | | // Offset(size.width / 2 + radius, size.height / 2), _bgPaint); |
| | | |
| | | for (var i = 1; i <= circleCount; ++i) { |
| | | canvas.drawCircle(Offset(size.width / 2, size.height / 2), |
| | | radius * i / circleCount, _bgPaint); |
| | | } |
| | | |
| | | _paint.shader = ui.Gradient.sweep( |
| | | Offset(size.width / 2, size.height / 2), |
| | | [Colors.white.withOpacity(.01), Colors.yellow.withOpacity(.6)], |
| | | [.0, 1.0], |
| | | TileMode.clamp, |
| | | .0, |
| | | pi / 4); |
| | | |
| | | canvas.save(); |
| | | double r = sqrt(pow(size.width, 2) + pow(size.height, 2)); |
| | | double startAngle = atan(size.height / size.width); |
| | | Point p0 = Point(r * cos(startAngle), r * sin(startAngle)); |
| | | Point px = Point(r * cos(angle + startAngle), r * sin(angle + startAngle)); |
| | | canvas.translate((p0.x - px.x) / 2, (p0.y - px.y) / 2); |
| | | canvas.rotate(angle); |
| | | |
| | | canvas.drawArc( |
| | | Rect.fromCircle( |
| | | center: Offset(size.width / 2, size.height / 2), radius: radius), |
| | | 0, |
| | | pi / 4, |
| | | true, |
| | | _paint); |
| | | canvas.restore(); |
| | | } |
| | | |
| | | @override |
| | | bool shouldRepaint(CustomPainter oldDelegate) { |
| | | return true; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter_unionad/flutter_unionad.dart'; |
| | | import 'package:flutter_tencentad/flutter_tencentad.dart'; |
| | | import '../model/common/adinfo_model.dart'; |
| | | import 'config_util.dart'; |
| | | import 'string_util.dart'; |
| | | import 'ui_constant.dart'; |
| | | |
| | | //紧急联系人输入框确定事件 |
| | | typedef OnAdCallback = void Function(bool success, String msg); |
| | | |
| | | typedef OnRewardAdCallback = void Function(RewardAdStatus status, String msg); |
| | | |
| | | enum RewardAdStatus { fail, click, ready, verify, close } |
| | | |
| | | class AdUtil { |
| | | static AdinfoModel? splashAdInfo; |
| | | |
| | | static Future init() async { |
| | | await CSJAdUtil.init(); |
| | | await GDTAdUtil.init(); |
| | | splashAdInfo = await getAdInfo(AdPosition.splash); |
| | | } |
| | | |
| | | static Widget loadSplash(AdinfoModel? adInfo, double width, double height, |
| | | OnAdCallback adCallback) { |
| | | if (adInfo == null) { |
| | | adCallback(false, "广告信息为空"); |
| | | return Container(); |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(adInfo.type)) { |
| | | adCallback(false, "广告类型为空"); |
| | | return Container(); |
| | | } |
| | | |
| | | if (adInfo.type == "csj") { |
| | | return CSJAdUtil.loadSplash(adInfo.pid!, width, height, adCallback); |
| | | } else { |
| | | return GDTAdUtil.loadSplash(adInfo.pid!, width, height, adCallback); |
| | | } |
| | | } |
| | | |
| | | static Widget? loadBanner( |
| | | AdinfoModel? adInfo, double width, double height, OnAdCallback callback) { |
| | | if (adInfo == null) { |
| | | callback(false, "广告信息为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(adInfo.type)) { |
| | | callback(false, "广告类型为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (adInfo.type == "csj") { |
| | | return CSJAdUtil.loadBanner(adInfo.pid!, width, height, callback); |
| | | } else { |
| | | return GDTAdUtil.loadBanner(adInfo.pid!, width, height, callback); |
| | | } |
| | | } |
| | | |
| | | static Widget? loadExpress( |
| | | AdinfoModel? adInfo, double width, double height, OnAdCallback callback) { |
| | | if (adInfo == null) { |
| | | callback(false, "广告信息为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(adInfo.type)) { |
| | | callback(false, "广告类型为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (adInfo.type == "csj") { |
| | | return CSJAdUtil.loadExpress(adInfo.pid!, width, height, callback); |
| | | } else { |
| | | return GDTAdUtil.loadExpress(adInfo.pid!, width, height, callback); |
| | | } |
| | | } |
| | | |
| | | static loadReward(AdinfoModel? adInfo, OnRewardAdCallback callback) async { |
| | | if (adInfo == null) { |
| | | callback(RewardAdStatus.fail, "广告信息为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(adInfo.type)) { |
| | | callback(RewardAdStatus.fail, "广告类型为空"); |
| | | return null; |
| | | } |
| | | |
| | | if (adInfo.type == "csj") { |
| | | return CSJAdUtil.loadReward(adInfo.pid!, callback); |
| | | } else { |
| | | return GDTAdUtil.loadReward(adInfo.pid!, callback); |
| | | } |
| | | } |
| | | |
| | | static loadInterstitial(AdinfoModel? adInfo, OnAdCallback callback) async { |
| | | if (adInfo == null) { |
| | | return null; |
| | | } |
| | | |
| | | if (StringUtil.isNullOrEmpty(adInfo.type)) { |
| | | return null; |
| | | } |
| | | |
| | | if (adInfo.type == "csj") { |
| | | CSJAdUtil.loadInterstitial(adInfo.pid!, callback); |
| | | } else { |
| | | GDTAdUtil.loadInterstitial(adInfo.pid!, callback); |
| | | } |
| | | } |
| | | |
| | | static Future<AdinfoModel?> getAdInfo(String position) async { |
| | | var result = await ConfigUtil.getConfig(position); |
| | | if (result == null) { |
| | | return null; |
| | | } |
| | | AdinfoModel model = AdinfoModel.fromJson(jsonDecode(result)); |
| | | if (StringUtil.isNullOrEmpty(model.type)) { |
| | | return null; |
| | | } |
| | | return model; |
| | | } |
| | | } |
| | | |
| | | class CSJAdUtil { |
| | | static Future init() async { |
| | | var csjAppId = "5240078"; |
| | | //初始化穿山甲 |
| | | if (!StringUtil.isNullOrEmpty(csjAppId)) { |
| | | // if (Platform.isAndroid) { |
| | | // await FlutterUnionad.andridPrivacy( |
| | | // isCanUseLocation: false, |
| | | // //是否允许SDK主动使用地理位置信息 true可以获取,false禁止获取。默认为true |
| | | // lat: 1.0, |
| | | // //当isCanUseLocation=false时,可传入地理位置信息,穿山甲sdk使用您传入的地理位置信息lat |
| | | // lon: 1.0, |
| | | // //当isCanUseLocation=false时,可传入地理位置信息,穿山甲sdk使用您传入的地理位置信息lon |
| | | // isCanUsePhoneState: false, |
| | | // //是否允许SDK主动使用手机硬件参数,如:imei |
| | | // imei: "123", |
| | | // //当isCanUsePhoneState=false时,可传入imei信息,穿山甲sdk使用您传入的imei信息 |
| | | // isCanUseWifiState: false, |
| | | // //是否允许SDK主动使用ACCESS_WIFI_STATE权限 |
| | | // isCanUseWriteExternal: false, |
| | | // //是否允许SDK主动使用WRITE_EXTERNAL_STORAGE权限 |
| | | // oaid: "111", //开发者可以传入oaid |
| | | // ); |
| | | // } |
| | | |
| | | await FlutterUnionad.register( |
| | | androidAppId: csjAppId, |
| | | //穿山甲广告 Android appid 必填 |
| | | iosAppId: "", |
| | | //穿山甲广告 ios appid 必填 |
| | | useTextureView: false, |
| | | //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView 选填 |
| | | appName: Constant.APP_NAME, |
| | | //appname 必填 |
| | | allowShowNotify: true, |
| | | //是否允许sdk展示通知栏提示 选填 |
| | | allowShowPageWhenScreenLock: true, |
| | | //是否在锁屏场景支持展示广告落地页 选填 |
| | | debug: true, |
| | | //是否显示debug日志 |
| | | supportMultiProcess: true, |
| | | //是否支持多进程,true支持 选填 |
| | | directDownloadNetworkType: [ |
| | | FlutterUnionadNetCode.NETWORK_STATE_4G, |
| | | FlutterUnionadNetCode.NETWORK_STATE_WIFI |
| | | ]); //允许直接下载的网络状态集合 选填 |
| | | } |
| | | } |
| | | |
| | | static Widget loadSplash( |
| | | String? pid, double width, double height, OnAdCallback adCallback) { |
| | | if (pid == null) { |
| | | adCallback(false, "pid为空"); |
| | | return Container(); |
| | | } |
| | | return FlutterUnionad.splashAdView( |
| | | //是否使用个性化模版 设定widget宽高 |
| | | mIsExpress: true, |
| | | //android 开屏广告广告id 必填 |
| | | androidCodeId: pid, |
| | | //ios 开屏广告广告id 必填 |
| | | iosCodeId: "", |
| | | //是否支持 DeepLink 选填 |
| | | supportDeepLink: true, |
| | | // 期望view 宽度 dp 选填 mIsExpress=true必填 |
| | | expressViewWidth: width, |
| | | //期望view高度 dp 选填 mIsExpress=true必填 |
| | | expressViewHeight: height, |
| | | callBack: FlutterUnionadSplashCallBack( |
| | | onShow: () { |
| | | print("开屏广告显示"); |
| | | }, |
| | | onClick: () { |
| | | print("开屏广告点击"); |
| | | }, |
| | | onFail: (error) { |
| | | adCallback(false, error); |
| | | }, |
| | | onFinish: () { |
| | | print("开屏广告倒计时结束"); |
| | | adCallback(true, ""); |
| | | }, |
| | | onSkip: () { |
| | | print("开屏广告跳过"); |
| | | adCallback(true, ""); |
| | | }, |
| | | onTimeOut: () { |
| | | print("开屏广告超时"); |
| | | adCallback(false, "开屏广告超时"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | static Widget loadBanner( |
| | | String pid, double width, double height, OnAdCallback callback) { |
| | | return FlutterUnionad.bannerAdView( |
| | | //andrrid banner广告id 必填 |
| | | androidCodeId: pid, |
| | | //ios banner广告id 必填 |
| | | iosCodeId: "", |
| | | //是否使用个性化模版 |
| | | mIsExpress: true, |
| | | //是否支持 DeepLink 选填 |
| | | supportDeepLink: true, |
| | | //一次请求广告数量 大于1小于3 必填 |
| | | expressAdNum: 3, |
| | | //轮播间隔事件 30-120秒 选填 |
| | | expressTime: 30, |
| | | // 期望view 宽度 dp 必填 |
| | | expressViewWidth: width, |
| | | //期望view高度 dp 必填 |
| | | expressViewHeight: height, |
| | | //广告事件回调 选填 |
| | | callBack: FlutterUnionadBannerCallBack(onShow: () { |
| | | print("banner广告加载完成"); |
| | | }, onDislike: (message) { |
| | | print("banner不感兴趣 $message"); |
| | | callback(false, "banner不感兴趣 $message"); |
| | | }, onFail: (error) { |
| | | print("banner广告加载失败 $error"); |
| | | }, onClick: () { |
| | | print("banner广告点击"); |
| | | }), |
| | | ); |
| | | } |
| | | |
| | | static Widget loadExpress( |
| | | String pid, double width, double height, OnAdCallback callback) { |
| | | return FlutterUnionad.nativeAdView( |
| | | androidCodeId: pid, |
| | | //android 信息流广告id 必填 |
| | | iosCodeId: "", |
| | | //ios banner广告id 必填 |
| | | supportDeepLink: true, |
| | | //是否支持 DeepLink 选填 |
| | | expressViewWidth: width, |
| | | // 期望view 宽度 dp 必填 |
| | | expressViewHeight: height, |
| | | //期望view高度 dp 必填 |
| | | expressNum: 1, |
| | | mIsExpress: true, |
| | | //一次请求广告数量 大于1小于3 必填 |
| | | callBack: FlutterUnionadNativeCallBack( |
| | | onShow: () { |
| | | print("信息流广告显示"); |
| | | }, |
| | | onFail: (error) { |
| | | print("信息流广告失败 $error"); |
| | | }, |
| | | onDislike: (message) { |
| | | print("信息流广告不感兴趣 $message"); |
| | | callback(false, "信息流广告不感兴趣 $message"); |
| | | }, |
| | | onClick: () { |
| | | print("信息流广告点击"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | static loadReward(String pid, OnRewardAdCallback adCallback) async { |
| | | FlutterUnionad.loadRewardVideoAd( |
| | | mIsExpress: true, |
| | | //是否个性化 选填 |
| | | androidCodeId: pid, |
| | | //Android 激励视频广告id 必填 |
| | | iosCodeId: "", |
| | | //ios 激励视频广告id 必填 |
| | | supportDeepLink: true, |
| | | //是否支持 DeepLink 选填 |
| | | rewardName: "vip", |
| | | //奖励名称 选填 |
| | | rewardAmount: 1, |
| | | //奖励数量 选填 |
| | | userID: "", |
| | | // 用户id 选填 |
| | | orientation: FlutterUnionadOrientation.VERTICAL, |
| | | //视屏方向 选填 |
| | | mediaExtra: null, //扩展参数 选填 |
| | | ); |
| | | |
| | | FlutterUnionadStream.initAdStream( |
| | | //激励广告 |
| | | flutterUnionadRewardAdCallBack: FlutterUnionadRewardAdCallBack( |
| | | onShow: () { |
| | | print("激励广告显示"); |
| | | }, |
| | | onClick: () { |
| | | print("激励广告点击"); |
| | | adCallback(RewardAdStatus.click, "激励广告点击"); |
| | | }, |
| | | onFail: (error) { |
| | | print("激励广告失败 $error"); |
| | | adCallback(RewardAdStatus.fail, "激励广告失败 $error"); |
| | | }, |
| | | onClose: () { |
| | | print("激励广告关闭"); |
| | | adCallback(RewardAdStatus.close, "激励广告关闭"); |
| | | }, |
| | | onSkip: () { |
| | | print("激励广告跳过"); |
| | | }, |
| | | onVerify: (bool isVerify, int rewardAmount, String rewardName, |
| | | int errorCode, String message) { |
| | | adCallback(RewardAdStatus.verify, "获取激励成功"); |
| | | }, |
| | | onReady: () async { |
| | | adCallback(RewardAdStatus.ready, "激励广告预加载准备就绪"); |
| | | //显示激励广告 |
| | | await FlutterUnionad.showRewardVideoAd(); |
| | | }, |
| | | onUnReady: () { |
| | | print("激励广告预加载未准备就绪"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | static loadInterstitial(String pid, OnAdCallback adCallback) async { |
| | | FlutterUnionad.loadFullScreenVideoAdInteraction( |
| | | androidCodeId: pid, //android 全屏广告id 必填 |
| | | iosCodeId: "", //ios 全屏广告id 必填 |
| | | supportDeepLink: true, //是否支持 DeepLink 选填 |
| | | orientation: FlutterUnionadOrientation.VERTICAL, //视屏方向 选填 |
| | | ); |
| | | |
| | | FlutterUnionadStream.initAdStream( |
| | | // 新模板渲染插屏广告回调 |
| | | flutterUnionadNewInteractionCallBack: |
| | | FlutterUnionadNewInteractionCallBack( |
| | | onShow: () { |
| | | print("新模板渲染插屏广告显示"); |
| | | }, |
| | | onSkip: () { |
| | | print("新模板渲染插屏广告跳过"); |
| | | }, |
| | | onClick: () { |
| | | print("新模板渲染插屏广告点击"); |
| | | }, |
| | | onFinish: () { |
| | | print("新模板渲染插屏广告结束"); |
| | | }, |
| | | onFail: (error) { |
| | | print("新模板渲染插屏广告错误 $error"); |
| | | adCallback(false, "新模板渲染插屏广告错误 $error"); |
| | | }, |
| | | onClose: () { |
| | | print("新模板渲染插屏广告关闭"); |
| | | adCallback(true, "新模板渲染插屏广告关闭"); |
| | | }, |
| | | onReady: () async { |
| | | print("新模板渲染插屏广告预加载准备就绪"); |
| | | //显示新模板渲染插屏 |
| | | await FlutterUnionad.showFullScreenVideoAdInteraction(); |
| | | }, |
| | | onUnReady: () { |
| | | print("新模板渲染插屏广告预加载未准备就绪"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class GDTAdUtil { |
| | | static Future init() async { |
| | | var gdtAppId = "1200343363"; |
| | | //初始化广点通 |
| | | if (!StringUtil.isNullOrEmpty(gdtAppId)) { |
| | | await FlutterTencentad.register( |
| | | androidId: gdtAppId, //androidId |
| | | iosId: "", //iosId |
| | | debug: true, //是否显示日志log |
| | | ); |
| | | } |
| | | } |
| | | |
| | | static Widget loadSplash( |
| | | String? pid, double width, double height, OnAdCallback adCallback) { |
| | | return FlutterTencentad.splashAdView( |
| | | //android广告id |
| | | androidId: pid!, |
| | | //ios广告id |
| | | iosId: "", |
| | | ////设置开屏广告从请求到展示所花的最大时长(并不是指广告曝光时长),取值范围为[1500, 5000]ms |
| | | fetchDelay: 3500, |
| | | //广告回调 |
| | | callBack: FlutterTencentadSplashCallBack( |
| | | onShow: () { |
| | | print("开屏广告显示"); |
| | | }, |
| | | onADTick: (time) { |
| | | print("开屏广告倒计时剩余时间 $time"); |
| | | }, |
| | | onClick: () { |
| | | print("开屏广告点击"); |
| | | }, |
| | | onClose: () { |
| | | print("开屏广告关闭"); |
| | | adCallback(true, "开屏广告关闭"); |
| | | }, |
| | | onExpose: () { |
| | | print("开屏广告曝光"); |
| | | }, |
| | | onFail: (code, message) { |
| | | adCallback(false, message); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | static Widget loadBanner( |
| | | String pid, double width, double height, OnAdCallback callback) { |
| | | return FlutterTencentad.bannerAdView( |
| | | //android广告id |
| | | androidId: pid, |
| | | //ios广告id |
| | | iosId: "", |
| | | //广告宽 单位dp |
| | | viewWidth: width, |
| | | //广告高 单位dp 宽高比应该为6.4:1 |
| | | viewHeight: height, |
| | | // 广告回调 |
| | | callBack: FlutterTencentadBannerCallBack( |
| | | onShow: () { |
| | | print("Banner广告显示"); |
| | | }, |
| | | onFail: (code, message) { |
| | | print("Banner广告错误 $code $message"); |
| | | callback(false, "Banner广告错误 $code $message"); |
| | | }, |
| | | onClose: () { |
| | | print("Banner广告关闭"); |
| | | callback(true, "Banner广告关闭"); |
| | | }, |
| | | onExpose: () { |
| | | print("Banner广告曝光"); |
| | | }, |
| | | onClick: () { |
| | | print("Banner广告点击"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | |
| | | static Widget loadExpress( |
| | | String pid, double width, double height, OnAdCallback callback) { |
| | | return FlutterTencentad.expressAdView( |
| | | //android广告id |
| | | androidId: pid, |
| | | //ios广告id |
| | | iosId: "", |
| | | //广告宽 单位dp |
| | | viewWidth: width.toInt(), |
| | | //广告高 单位dp |
| | | viewHeight: height.toInt(), |
| | | //回调事件 |
| | | callBack: FlutterTencentadExpressCallBack( |
| | | onShow: () { |
| | | print("动态信息流广告显示"); |
| | | }, |
| | | onFail: (code, message) { |
| | | print("动态信息流广告错误 $code $message"); |
| | | }, |
| | | onClose: () { |
| | | print("动态信息流广告关闭"); |
| | | }, |
| | | onExpose: () { |
| | | print("动态信息流广告曝光"); |
| | | }, |
| | | onClick: () { |
| | | print("动态信息流广告点击"); |
| | | }, |
| | | )); |
| | | } |
| | | |
| | | static loadReward(String pid, OnRewardAdCallback adCallback) async { |
| | | await FlutterTencentad.loadRewardVideoAd( |
| | | //android广告id |
| | | androidId: pid, |
| | | //ios广告id |
| | | iosId: "", |
| | | //用户id |
| | | userID: "", |
| | | //奖励 |
| | | rewardName: "VIP", |
| | | //奖励数 |
| | | rewardAmount: 1, |
| | | //扩展参数 服务器回调使用 |
| | | customData: ""); |
| | | |
| | | FlutterTencentAdStream.initAdStream( |
| | | //激励广告 |
| | | flutterTencentadRewardCallBack: |
| | | FlutterTencentadRewardCallBack(onShow: () { |
| | | print("激励广告显示"); |
| | | }, onClick: () { |
| | | print("激励广告点击"); |
| | | adCallback(RewardAdStatus.click, "激励广告点击"); |
| | | }, onFail: (code, message) { |
| | | print("激励广告失败 $code $message"); |
| | | adCallback(RewardAdStatus.fail, "激励广告失败"); |
| | | }, onClose: () { |
| | | print("激励广告关闭"); |
| | | adCallback(RewardAdStatus.close, "激励广告关闭"); |
| | | }, onReady: () async { |
| | | print("激励广告预加载准备就绪"); |
| | | adCallback(RewardAdStatus.ready, "激励广告预加载准备就绪"); |
| | | await FlutterTencentad.showRewardVideoAd(); |
| | | }, onUnReady: () { |
| | | print("激励广告预加载未准备就绪"); |
| | | }, onVerify: (transId, rewardName, rewardAmount) { |
| | | print("激励广告奖励 $transId $rewardName $rewardAmount"); |
| | | adCallback(RewardAdStatus.verify, "激励广告奖励"); |
| | | }, onFinish: () { |
| | | print("激励广告完成"); |
| | | }), |
| | | ); |
| | | } |
| | | |
| | | static loadInterstitial(String pid, OnAdCallback adCallback) async { |
| | | await FlutterTencentad.loadUnifiedInterstitialAD( |
| | | //android广告id |
| | | androidId: pid, |
| | | //ios广告id |
| | | iosId: "", |
| | | //是否全屏 |
| | | isFullScreen: false, |
| | | ); |
| | | |
| | | FlutterTencentAdStream.initAdStream( |
| | | flutterTencentadInteractionCallBack: FlutterTencentadInteractionCallBack( |
| | | onShow: () { |
| | | print("插屏广告显示"); |
| | | }, |
| | | onClick: () { |
| | | print("插屏广告点击"); |
| | | }, |
| | | onFail: (code, message) { |
| | | print("插屏广告失败 $code $message"); |
| | | adCallback(false, "插屏广告失败 $code $message"); |
| | | }, |
| | | onClose: () { |
| | | print("插屏广告关闭"); |
| | | adCallback(true, "插屏广告关闭"); |
| | | }, |
| | | onReady: () async { |
| | | print("插屏广告预加载准备就绪"); |
| | | await FlutterTencentad.showUnifiedInterstitialAD(); |
| | | }, |
| | | onUnReady: () { |
| | | print("插屏广告预加载未准备就绪"); |
| | | }, |
| | | ), |
| | | ); |
| | | } |
| | | } |
| | | |
| | | class AdPosition { |
| | | //开屏 |
| | | static String splash = "splash"; |
| | | |
| | | //首页插屏 |
| | | static String homeInterstitial = "homeInterstitial"; |
| | | |
| | | //我的页面原生 |
| | | static String mineExpress = "mineExpress"; |
| | | |
| | | //搜索页面原生 |
| | | static String searchExpress = "searchExpress"; |
| | | |
| | | //搜索结果banner |
| | | static String searchResultBanner = "searchResultBanner"; |
| | | |
| | | //轨迹分享页插屏 |
| | | static String travelShareInterstitial = "travelShareInterstitial"; |
| | | |
| | | //会员激励视频 |
| | | static String vipReward = "vipReward"; |
| | | } |
New file |
| | |
| | | import 'dart:io'; |
| | | |
| | | import 'package:device_info/device_info.dart'; |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart'; |
| | | import 'package:jpush_flutter/jpush_flutter.dart'; |
| | | import 'package:package_info/package_info.dart'; |
| | | |
| | | import 'ad_util.dart'; |
| | | import 'global.dart'; |
| | | import 'push_util.dart'; |
| | | |
| | | class AppUtil { |
| | | static final JPush _jpush = JPush(); |
| | | |
| | | static bool _inited = false; |
| | | |
| | | //初始化应用 |
| | | static Future<bool> initApp(BuildContext context) async { |
| | | if (_inited) { |
| | | return true; |
| | | } |
| | | _inited = true; |
| | | print("initApp"); |
| | | await registerWxApi( |
| | | appId: "wxd930ea5d5a228f5f", |
| | | universalLink: "https://your.univerallink.com/link/"); |
| | | |
| | | //初始化广告 |
| | | await AdUtil.init(); |
| | | |
| | | //初始化本地应用 |
| | | await _initNativeApp(); |
| | | //初始化极光 |
| | | try { |
| | | PushUtil.init(context); |
| | | } catch (e) {} |
| | | //初始化版本 |
| | | if (Platform.isAndroid) { |
| | | DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); |
| | | AndroidDeviceInfo _androidInfo = await deviceInfo.androidInfo; |
| | | Global.androidSDK = _androidInfo.version.sdkInt; |
| | | } |
| | | |
| | | // //初始化阿里云授权登录 |
| | | // await LoginPage.messageChannel.send({ |
| | | // "method": "init", |
| | | // "secret": Constant.ALIYUN_AUTH_SECRETINFO, |
| | | // "privacy": Constant.PRIVACY_URL, |
| | | // "protocol": Constant.PROTOCOL_URL |
| | | // }) as Map; |
| | | |
| | | return true; |
| | | } |
| | | |
| | | //本地应用初始化 |
| | | static _initNativeApp() async { |
| | | if (Platform.isAndroid) { |
| | | const platform = MethodChannel("com.yeshi.location/init"); //分析1 |
| | | try { |
| | | await platform.invokeMethod("initApp"); //分析2 |
| | | } on PlatformException catch (e) { |
| | | print(e.toString()); |
| | | } |
| | | //填充utdid |
| | | await Global.loadUtdId(); |
| | | //填充channel |
| | | await Global.loadChannel(); |
| | | } |
| | | } |
| | | |
| | | static Future<int> getVersionCode() async { |
| | | PackageInfo packageInfo = await PackageInfo.fromPlatform(); |
| | | return int.parse(packageInfo.buildNumber); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:io'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | |
| | | /// 缓存管理类 |
| | | /// ./lib/utils/cache_util.dart |
| | | class CacheUtil { |
| | | /// 获取缓存大小 |
| | | static Future<int> total() async { |
| | | Directory tempDir = await getTemporaryDirectory(); |
| | | if (tempDir == null) return 0; |
| | | int total = await _reduce(tempDir); |
| | | return total; |
| | | } |
| | | |
| | | /// 清除缓存 |
| | | static Future<void> clear() async { |
| | | Directory tempDir = await getTemporaryDirectory(); |
| | | if (tempDir == null) return; |
| | | await _delete(tempDir); |
| | | } |
| | | |
| | | /// 递归缓存目录,计算缓存大小 |
| | | static Future<int> _reduce(final FileSystemEntity file) async { |
| | | /// 如果是一个文件,则直接返回文件大小 |
| | | if (file is File) { |
| | | int length = await file.length(); |
| | | return length; |
| | | } |
| | | |
| | | /// 如果是目录,则遍历目录并累计大小 |
| | | if (file is Directory) { |
| | | final List<FileSystemEntity> children = file.listSync(); |
| | | |
| | | int total = 0; |
| | | |
| | | if (children != null && children.isNotEmpty) |
| | | for (final FileSystemEntity child in children) |
| | | total += await _reduce(child); |
| | | |
| | | return total; |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | | |
| | | /// 递归删除缓存目录和文件 |
| | | static Future<void> _delete(FileSystemEntity file) async { |
| | | if (file is Directory) { |
| | | final List<FileSystemEntity> children = file.listSync(); |
| | | for (final FileSystemEntity child in children) { |
| | | await _delete(child); |
| | | } |
| | | } else { |
| | | await file.delete(); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import '../api/http.dart'; |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | |
| | | class ConfigUtil { |
| | | ///保存配置信息 |
| | | static void saveConfig(Map<String, dynamic> map) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | await prefs.setString("config_value", jsonEncode(map)); |
| | | } |
| | | |
| | | static Future<String?> getConfig(String key) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | String? result = prefs.getString("config_value"); |
| | | if (result != null) { |
| | | Map<String, dynamic> map = jsonDecode(result); |
| | | return map[key]; |
| | | } else { |
| | | //重新请求 |
| | | ConfigApiUtil.getConfig().then((value) { |
| | | if (value == null) { |
| | | return; |
| | | } |
| | | if (value["code"] == 0) { |
| | | saveConfig(value["data"]); |
| | | } |
| | | }); |
| | | } |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | class ConfigKey { |
| | | //客服 |
| | | static const String kefu = "kefu"; |
| | | |
| | | //教程 |
| | | static const String course = "course"; |
| | | |
| | | //注销 |
| | | static const String unRegister = "unRegister"; |
| | | |
| | | //隐私投诉 |
| | | static const String privacyComplain = "privacyComplain"; |
| | | |
| | | //会员链接 |
| | | static const String vipLink = "vipLink"; |
| | | |
| | | //三方SDK链接 |
| | | static const String sdkList = "sdkList"; |
| | | } |
| | | |
| | | enum SharePlatform { wx, wxcircle, qq, qqzone, sina } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'package:crypto/crypto.dart'; |
| | | |
| | | class EncryptUtil { |
| | | static String MD5(String data) { |
| | | return md5.convert(utf8.encode(data)).toString(); |
| | | } |
| | | } |
New file |
| | |
| | | import 'package:event_bus/event_bus.dart'; |
| | | EventBus eventBus = EventBus(); |
| | | |
| | | |
| | | |
| | | class LoginEventBus { |
| | | final bool isLogin; |
| | | LoginEventBus(this.isLogin); |
| | | } |
| | | |
New file |
| | |
| | | import 'package:flutter/material.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | |
| | | //全局跳转 |
| | | final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); |
| | | class Global { |
| | | static const messageChannel = |
| | | BasicMessageChannel('DeviceUtil', StandardMessageCodec()); |
| | | |
| | | static String? utdId; |
| | | |
| | | static String? channel; |
| | | |
| | | //android的版本 |
| | | static int? androidSDK; |
| | | |
| | | static Future loadUtdId() async { |
| | | String? value = |
| | | await messageChannel.send({"method": "getUtdid"}) as String?; |
| | | utdId = value; |
| | | } |
| | | |
| | | static Future loadChannel() async { |
| | | String? value = |
| | | await messageChannel.send({"method": "getChannel"}) as String?; |
| | | channel = value; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | |
| | | import 'package:dio/dio.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:flutter/widgets.dart'; |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | import '../api/http.dart' as http; |
| | | import '../utils/ad_util.dart'; |
| | | import '../utils/encrypt_util.dart'; |
| | | import '../utils/permission_util.dart'; |
| | | import '../utils/share_utils.dart'; |
| | | import '../utils/string_util.dart'; |
| | | import '../utils/ui_constant.dart'; |
| | | import '../utils/ui_utils.dart'; |
| | | import '../utils/user_util.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | import 'package:webview_flutter/platform_interface.dart'; |
| | | import 'package:webview_flutter/webview_flutter.dart'; |
| | | import 'package:path_provider/path_provider.dart'; |
| | | |
| | | import 'config_util.dart'; |
| | | |
| | | class JavascriptInterface { |
| | | final BuildContext context; |
| | | final WebViewController? _controller; |
| | | |
| | | JavascriptInterface( |
| | | BuildContext this.context, WebViewController? this._controller); |
| | | |
| | | Set<JavascriptChannel> getInterfaces() { |
| | | List<JavascriptChannel> list = []; |
| | | list.add(JavascriptChannel( |
| | | name: 'yestv', |
| | | onMessageReceived: (JavascriptMessage message) { |
| | | print("onMessageReceived"); |
| | | var data = jsonDecode(message.message); |
| | | String method = data["method"]; |
| | | var params = data["params"]; |
| | | String? _callback = data["callback"]; |
| | | switch (method) { |
| | | case "toast": |
| | | toast(params); |
| | | break; |
| | | case "copyText": |
| | | copyText(params); |
| | | break; |
| | | case "getUid": |
| | | getUid(params, _callback); |
| | | break; |
| | | case "getAppName": |
| | | getAppName(_callback); |
| | | break; |
| | | case "getRequestBaseParams": |
| | | getRequestBaseParams(params, _callback); |
| | | break; |
| | | case "showRewardVideoAd": |
| | | showRewardVideoAd(_callback); |
| | | break; |
| | | case "showLoading": |
| | | showLoading(); |
| | | break; |
| | | case "hideLoading": |
| | | hideLoading(); |
| | | break; |
| | | case "finishPage": |
| | | finishPage(); |
| | | break; |
| | | case "saveImg": |
| | | String url = params["url"]; |
| | | saveImg(url); |
| | | break; |
| | | case "shareImg": |
| | | String url = params["url"]; |
| | | String type = params["type"]; |
| | | shareImg(url, int.parse(type)); |
| | | break; |
| | | } |
| | | })); |
| | | return list.toSet(); |
| | | } |
| | | |
| | | callback(String method, var params, {bool finish = true}) { |
| | | _controller!.runJavascript("$method('$params')"); |
| | | if (finish) { |
| | | _controller!.runJavascript("delete $method"); |
| | | } |
| | | } |
| | | |
| | | //获取用户ID |
| | | getUid(var params, String? callbackName) { |
| | | if (callbackName != null) { |
| | | UserUtil.getUid().then((value) { |
| | | callback(callbackName, value != null ? value.toString() : ""); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | //获取用户ID |
| | | getAppName(String? callbackName) { |
| | | if (callbackName != null) { |
| | | callback(callbackName, Constant.APP_NAME); |
| | | } |
| | | } |
| | | |
| | | //toast |
| | | toast(params) { |
| | | if (params != null && params["msg"] != null) { |
| | | Fluttertoast.showToast(msg: params["msg"]); |
| | | } |
| | | } |
| | | |
| | | copyText(params) { |
| | | if (params != null && params["content"] != null) { |
| | | Clipboard.setData(ClipboardData(text: params["content"])); |
| | | } |
| | | } |
| | | |
| | | //获取基本的网络请求参数 |
| | | getRequestBaseParams(var params, String? callbackName) { |
| | | var ps = {}; |
| | | if (params != null) { |
| | | ps.addAll(params); |
| | | } |
| | | http.HttpUtil.getBaseParams(params).then((value) { |
| | | String result = jsonEncode(value); |
| | | if (callbackName != null) { |
| | | callback(callbackName, result); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | //展示激励视频 |
| | | showRewardVideoAd(String? callbackName) { |
| | | AdUtil.getAdInfo(AdPosition.vipReward).then((value) { |
| | | AdUtil.loadReward(value, (status, msg) { |
| | | switch (status) { |
| | | case RewardAdStatus.verify: |
| | | callback(callbackName!, 3, finish: false); |
| | | break; |
| | | case RewardAdStatus.ready: |
| | | callback(callbackName!, 1, finish: false); |
| | | break; |
| | | case RewardAdStatus.close: |
| | | callback(callbackName!, 10, finish: true); |
| | | break; |
| | | case RewardAdStatus.click: |
| | | callback(callbackName!, 2, finish: false); |
| | | break; |
| | | case RewardAdStatus.fail: |
| | | callback(callbackName!, 0, finish: true); |
| | | break; |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | showLoading() { |
| | | http.showLoading(context); |
| | | } |
| | | |
| | | hideLoading() { |
| | | Navigator.of(context).pop(); |
| | | } |
| | | |
| | | //结束页面 |
| | | finishPage() { |
| | | Navigator.of(context).pop(); |
| | | } |
| | | |
| | | Future<bool> _dowloadImg(String url, String path) async { |
| | | PermissionStatus status = |
| | | await PermissionUtil.openPermission(Permission.storage, force: true); |
| | | if (status != PermissionStatus.granted) { |
| | | return false; |
| | | } |
| | | |
| | | //下载图片 |
| | | Dio dio = Dio(); |
| | | //设置连接超时时间 |
| | | dio.options.connectTimeout = 20000; |
| | | //设置数据接收超时时间 |
| | | dio.options.receiveTimeout = 20000; |
| | | Response response; |
| | | try { |
| | | response = await dio.download(url, path); |
| | | if (response.statusCode == 200) { |
| | | return true; |
| | | } else { |
| | | return false; |
| | | } |
| | | } catch (e) { |
| | | ToastUtil.toast("网络连接失败"); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | //保存图片 |
| | | saveImg(String url) { |
| | | getExternalStorageDirectory().then((value) { |
| | | if (value == null) { |
| | | ToastUtil.toast("获取缓存目录失败"); |
| | | return; |
| | | } |
| | | |
| | | String doc = value.path; |
| | | String path = doc + "/" + EncryptUtil.MD5(url) + ".png"; |
| | | _dowloadImg(url, path).then((value) { |
| | | if (value) { |
| | | ToastUtil.toast("保存成功"); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | ///分享图片 |
| | | ///type: 1-微信 2-qq 3-新浪 |
| | | shareImg(String url, int type) { |
| | | getTemporaryDirectory().then((value) { |
| | | String path = value.path + "/" + EncryptUtil.MD5(url) + ".png"; |
| | | _dowloadImg(url, path).then((value) { |
| | | if (value) { |
| | | //开始分享 |
| | | switch (type) { |
| | | case 1: |
| | | ShareUtil.shareImg(context, File(path), SharePlatform.wx); |
| | | break; |
| | | case 2: |
| | | ShareUtil.shareImg(context, File(path), SharePlatform.qq); |
| | | break; |
| | | case 3: |
| | | ShareUtil.shareImg(context, File(path), SharePlatform.sina); |
| | | break; |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | |
| | | import 'global.dart'; |
| | | |
| | | typedef PageDataLisener = void Function(dynamic data); |
| | | |
| | | //滑动效果 |
| | | class CustomRouteSlide extends PageRouteBuilder { |
| | | final Widget widget; |
| | | |
| | | CustomRouteSlide(this.widget) |
| | | : super( |
| | | transitionDuration: const Duration(milliseconds: 500), |
| | | pageBuilder: (BuildContext context, Animation<double> animation1, |
| | | Animation<double> animation2) { |
| | | return widget; |
| | | }, |
| | | transitionsBuilder: (BuildContext context, |
| | | Animation<double> animation1, |
| | | Animation<double> animation2, |
| | | Widget child) { |
| | | return SlideTransition( |
| | | position: Tween<Offset>( |
| | | begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0)) |
| | | .animate(CurvedAnimation( |
| | | parent: animation1, curve: Curves.fastOutSlowIn)), |
| | | child: child, |
| | | ); |
| | | }); |
| | | } |
| | | |
| | | class NavigatorUtil { |
| | | // static void navigateToNextPage(BuildContext context, PageRoute route, |
| | | // PageDataLisener? dataLisener) async { |
| | | // final result = await Navigator.of(context).push(route); |
| | | // dataLisener!(result); |
| | | // } |
| | | |
| | | static void navigateToNextPage( |
| | | BuildContext context, Widget page, PageDataLisener? dataLisener) async { |
| | | final result = |
| | | await Navigator.of(context).push(CupertinoPageRoute(builder: (context) { |
| | | return page; |
| | | })); |
| | | dataLisener!(result); |
| | | } |
| | | |
| | | static void navigateToNextPagePush(Widget page) { |
| | | |
| | | navigatorKey.currentState!.push( |
| | | CupertinoPageRoute (builder: (BuildContext context) => page)); |
| | | } |
| | | |
| | | static void navigateToNextPageWithFinish( |
| | | BuildContext context, PageRoute route) { |
| | | Navigator.of(context).pushReplacement(route); |
| | | } |
| | | } |
| | | |
| | | class KeepAliveWrapper extends StatefulWidget { |
| | | const KeepAliveWrapper({ |
| | | Key? key, |
| | | this.keepAlive = true, |
| | | required this.child, |
| | | }) : super(key: key); |
| | | final bool keepAlive; |
| | | final Widget child; |
| | | |
| | | @override |
| | | _KeepAliveWrapperState createState() => _KeepAliveWrapperState(); |
| | | } |
| | | |
| | | class _KeepAliveWrapperState extends State<KeepAliveWrapper> |
| | | with AutomaticKeepAliveClientMixin { |
| | | @override |
| | | Widget build(BuildContext context) { |
| | | super.build(context); |
| | | return widget.child; |
| | | } |
| | | |
| | | @override |
| | | void didUpdateWidget(covariant KeepAliveWrapper oldWidget) { |
| | | if (oldWidget.keepAlive != widget.keepAlive) { |
| | | // keepAlive 状态需要更新,实现在 AutomaticKeepAliveClientMixin 中 |
| | | updateKeepAlive(); |
| | | } |
| | | super.didUpdateWidget(oldWidget); |
| | | } |
| | | |
| | | @override |
| | | bool get wantKeepAlive => widget.keepAlive; |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | |
| | | import '../utils/global.dart'; |
| | | import 'package:permission_handler/permission_handler.dart'; |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | |
| | | import 'event_bus_util.dart'; |
| | | |
| | | class PermissionUtil { |
| | | static var deniedSets = Set(); |
| | | |
| | | static Permission getLocationPermission() { |
| | | if (Platform.isAndroid) { |
| | | //获取系统版本 |
| | | if (Global.androidSDK != null && Global.androidSDK! < 29) { |
| | | return Permission.locationAlways; |
| | | } else { |
| | | return Permission.location; |
| | | } |
| | | } else { |
| | | return Permission.locationAlways; |
| | | } |
| | | } |
| | | |
| | | static Future _loadDeniedPermissions() async { |
| | | //加载 |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | List<String>? list = prefs.getStringList("permission_delay_list"); |
| | | deniedSets.clear(); |
| | | if (list != null) { |
| | | deniedSets.addAll(list); |
| | | } |
| | | |
| | | print(jsonEncode(list)); |
| | | } |
| | | |
| | | static Future _denyPermission(Permission permission) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | List<String>? list = prefs.getStringList("permission_delay_list"); |
| | | list ??= []; |
| | | bool hasAdd = false; |
| | | list.forEach((element) { |
| | | if (element == permission.value.toString()) { |
| | | hasAdd = true; |
| | | } |
| | | }); |
| | | |
| | | if (!hasAdd) { |
| | | list.add(permission.value.toString()); |
| | | } |
| | | await prefs.setStringList("permission_delay_list", list); |
| | | } |
| | | |
| | | static Future _removeDenyPermission(Permission permission) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | List<String>? list = prefs.getStringList("permission_delay_list"); |
| | | list ??= []; |
| | | |
| | | for (int i = 0; i < list.length; i++) { |
| | | if (list[i] == permission.value.toString()) { |
| | | list.removeAt(i); |
| | | i--; |
| | | } |
| | | } |
| | | await prefs.setStringList("permission_delay_list", list); |
| | | } |
| | | |
| | | ///打开应用设置 |
| | | static openAppSetting() async { |
| | | await openAppSettings(); |
| | | } |
| | | |
| | | ///打开权限, |
| | | ///force:强制打开,权限被拒绝后记录 |
| | | static Future<PermissionStatus> openPermission(Permission permission, |
| | | {force: false}) async { |
| | | await _loadDeniedPermissions(); |
| | | PermissionStatus status = await permission.status; |
| | | PermissionStatus? resultStatus; |
| | | switch (status) { |
| | | //Android授权 |
| | | case PermissionStatus.granted: |
| | | resultStatus = status; |
| | | break; |
| | | //Android拒绝 |
| | | case PermissionStatus.denied: |
| | | if (deniedSets.contains(permission.value.toString()) && !force) { |
| | | resultStatus = PermissionStatus.denied; |
| | | } else { |
| | | resultStatus = await permission.request(); |
| | | } |
| | | break; |
| | | //Android禁止后不再提示 |
| | | case PermissionStatus.permanentlyDenied: |
| | | if (deniedSets.contains(permission.value.toString()) && !force) { |
| | | resultStatus = PermissionStatus.permanentlyDenied; |
| | | } else { |
| | | bool success = await openAppSettings(); |
| | | resultStatus = await permission.status; |
| | | } |
| | | break; |
| | | //IOS |
| | | case PermissionStatus.limited: |
| | | if (deniedSets.contains(permission.value.toString()) && !force) { |
| | | resultStatus = PermissionStatus.limited; |
| | | } else { |
| | | resultStatus = await permission.request(); |
| | | } |
| | | break; |
| | | //IOS |
| | | case PermissionStatus.restricted: |
| | | if (deniedSets.contains(permission.value.toString()) && !force) { |
| | | resultStatus = PermissionStatus.restricted; |
| | | } else { |
| | | resultStatus = await permission.request(); |
| | | } |
| | | break; |
| | | } |
| | | |
| | | if (resultStatus == PermissionStatus.granted) { |
| | | _removeDenyPermission(permission); |
| | | } else { |
| | | _denyPermission(permission); |
| | | } |
| | | |
| | | return resultStatus; |
| | | } |
| | | |
| | | ///批量打开权限 |
| | | static openPermissions(List<Permission> permissions, {force: true}) async { |
| | | await _loadDeniedPermissions(); |
| | | List<Permission> requestPS = []; |
| | | permissions.forEach((element) { |
| | | if (!deniedSets.contains(element.value.toString())) { |
| | | requestPS.add(element); |
| | | } |
| | | }); |
| | | |
| | | if (requestPS.isNotEmpty) { |
| | | await requestPS.request(); |
| | | } |
| | | } |
| | | |
| | | ///关闭权限 |
| | | static Future<PermissionStatus> closePermission(Permission permission) async { |
| | | bool success = await openAppSettings(); |
| | | return await permission.status; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:convert'; |
| | | import 'dart:io'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:jpush_flutter/jpush_flutter.dart'; |
| | | import '../api/http.dart'; |
| | | import '../model/user/user_info.dart'; |
| | | import '../utils/event_bus_util.dart'; |
| | | import '../utils/pageutils.dart'; |
| | | import '../utils/user_util.dart'; |
| | | |
| | | import 'global.dart'; |
| | | |
| | | class PushUtil { |
| | | static final JPush _jpush = JPush(); |
| | | |
| | | static init(BuildContext context) async { |
| | | try { |
| | | _jpush.addEventHandler( |
| | | onReceiveNotification: (Map<String, dynamic> message) async { |
| | | print("flutter onReceiveNotification: $message"); |
| | | }, onOpenNotification: (Map<String, dynamic> message) async { |
| | | var extra = message["extras"]["cn.jpush.android.EXTRA"]; |
| | | extra = jsonDecode(extra); |
| | | // //打开页面 |
| | | // var type = extra["type"]; |
| | | // |
| | | // if (type == "sos") { |
| | | // //SOS |
| | | // NavigatorUtil.navigateToNextPagePush(SOSPage(title: "")); |
| | | // } else if (type == "locationInvite") { |
| | | // //请求定位 |
| | | // eventBus.fire(LocationInviteEventBus()); |
| | | // } |
| | | }, onReceiveMessage: (Map<String, dynamic> message) async { |
| | | var data = jsonDecode(message["message"]); |
| | | print("flutter onReceiveMessage: $data"); |
| | | var type = data["type"]; |
| | | // if (type == "sos") { |
| | | // //SOS |
| | | // NavigatorUtil.navigateToNextPagePush(SOSPage(title: "")); |
| | | // } else if (type == "locationInvite") { |
| | | // eventBus.fire(LocationInviteEventBus()); |
| | | // } |
| | | }, onReceiveNotificationAuthorization: |
| | | (Map<String, dynamic> message) async { |
| | | print("flutter onReceiveNotificationAuthorization: $message"); |
| | | }); |
| | | } on PlatformException {} |
| | | |
| | | _jpush.setup( |
| | | appKey: "987d3d50f209994fa522d001", //你自己应用的 AppKey |
| | | channel: "developer-default", |
| | | production: false, |
| | | debug: true, |
| | | ); |
| | | _jpush.applyPushAuthority( |
| | | NotificationSettingsIOS(sound: true, alert: true, badge: true)); |
| | | |
| | | // Platform messages may fail, so we use a try/catch PlatformException. |
| | | _jpush.getRegistrationID().then((rid) { |
| | | print("flutter get registration id : $rid"); |
| | | UserApiUtil.uploadPushRegId(context, rid); |
| | | }); |
| | | |
| | | //如果登录了就设置用户的uid |
| | | bool isLogin = await UserUtil.isLogin(); |
| | | if (isLogin) { |
| | | UserInfo? user = await UserUtil.getUserInfo(); |
| | | setAlias(user!.id!.toString()); |
| | | } |
| | | } |
| | | |
| | | ///添加alias |
| | | static Future setAlias(String alias) async { |
| | | try { |
| | | await _jpush.setAlias(alias); |
| | | } catch (e) {} |
| | | } |
| | | |
| | | //删除alias |
| | | static Future removeAlias() async { |
| | | await _jpush.deleteAlias(); |
| | | } |
| | | } |
New file |
| | |
| | | |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | |
| | | class SettingUtil { |
| | | //设置推送 |
| | | static Future<bool> setPush(bool enable) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | return await prefs.setBool("setting_push", enable); |
| | | } |
| | | |
| | | ///是否允许推送 |
| | | static Future<bool> isEnablePush() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | bool? result = prefs.getBool("setting_push"); |
| | | result ??= true; |
| | | return result; |
| | | } |
| | | |
| | | //设置推荐广告 |
| | | static Future<bool> setRecommendAd(bool enable) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | return await prefs.setBool("setting_recommend_ad", enable); |
| | | } |
| | | |
| | | ///是否允许推荐广告 |
| | | static Future<bool> isEnableRecommendAd() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | bool? result = prefs.getBool("setting_recommend_ad"); |
| | | result ??= true; |
| | | return result; |
| | | } |
| | | |
| | | //设置推荐广告 |
| | | static Future<bool> setLocationSpan(int second) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | return await prefs.setInt("setting_location_span", second); |
| | | } |
| | | |
| | | ///是否允许推荐广告 |
| | | static Future<int> getLocationSpan() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | int? result = prefs.getInt("setting_location_span"); |
| | | result ??= 30; |
| | | return result; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:io'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:share_plus/share_plus.dart'; |
| | | |
| | | import 'config_util.dart'; |
| | | |
| | | class ShareUtil { |
| | | static shareImg( |
| | | BuildContext context, File f, SharePlatform sharePlatform) async { |
| | | if (Platform.isAndroid) { |
| | | const platform = MethodChannel("com.yeshi.location/share"); //分析1 |
| | | bool result = false; |
| | | try { |
| | | var params = { |
| | | "path": f.path, |
| | | "platform": sharePlatform.runtimeType.toString() |
| | | }; |
| | | switch (sharePlatform) { |
| | | case SharePlatform.qq: |
| | | params["platform"] = "qq"; |
| | | break; |
| | | case SharePlatform.wx: |
| | | params["platform"] = "wx"; |
| | | break; |
| | | case SharePlatform.sina: |
| | | params["platform"] = "sina"; |
| | | break; |
| | | } |
| | | |
| | | result = await platform.invokeMethod("shareImg", params); //分析2 |
| | | } on PlatformException catch (e) { |
| | | print(e.toString()); |
| | | } |
| | | } else { |
| | | Share.shareFiles([f.path]); |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | class StringUtil { |
| | | //是否为电话号码 |
| | | static bool isMobile(String str) { |
| | | return RegExp( |
| | | '^((13[0-9])|(15[^4])|(166)|(17[0-8])|(18[0-9])|(19[8-9])|(147,145))\\d{8}\$') |
| | | .hasMatch(str); |
| | | } |
| | | |
| | | static bool isNullOrEmpty(String? str) { |
| | | return str==null|| str.isEmpty || str.trim().isEmpty; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | |
| | | //滑动效果 |
| | | class ColorConstant { |
| | | static const Color theme = Color(0xFF0078FF);//Color(0xFF0E95FE); |
| | | static const Color title = Color(0xFF333333); |
| | | } |
| | | |
| | | class Constant { |
| | | |
| | | static const String APP_NAME = |
| | | "定位追踪轨迹"; |
| | | |
| | | //阿里云授权登录 |
| | | static const String ALIYUN_AUTH_SECRETINFO = |
| | | "v+dQBemz/CZaLI0YP/A5AxxG2YgF7IvP+RNzRkmOGln1bbd7tcMt7uvqt8dvb9ekawjGbvSZ6Y/N9WT0kpUb6lrkS11BxfhCpXtuxmOxei97xP3l5Hd8PVqPv2jPC8uVDRhl6kaAqf/6I1gwL1d7am+8w1sGkYnZ3UEgd9ljDBKjeRbbpp+KEzLiqnKWYDNqMLSRdU0BmzTSGqtkM5c1TYOZgx68NxwE2oM9VzcjQEeFP0yiQatMyNIQ5mJjbyU3zi9qiyMQaeTLHeACvqZ2XCYQBbAeqJh6DPrhIHGlfGc="; |
| | | |
| | | //隐私政策链接 |
| | | static const String PRIVACY_URL = |
| | | "http://web.location.izzql.com/privacy.html"; |
| | | |
| | | //用户协议链接 |
| | | static const String PROTOCOL_URL = |
| | | "http://web.location.izzql.com/user_protocol.html"; |
| | | |
| | | //微信 |
| | | static const String WX_APPID = "wxd930ea5d5a228f5f"; |
| | | static const String WX_UNIVERSAL_LINK = "https://your.univerallink.com/link/"; |
| | | |
| | | static const String APP_DOWNLOAD_LINK = |
| | | "https://a.app.qq.com/o/simple.jsp?pkgname=com.dw.zzql"; |
| | | |
| | | |
| | | static const String MAP_LINK = |
| | | "http://web.location.izzql.com/map/map.html"; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:fluttertoast/fluttertoast.dart'; |
| | | import 'package:flutter/material.dart'; |
| | | |
| | | class ToastUtil { |
| | | static toast(String text) { |
| | | Fluttertoast.showToast(msg: text); |
| | | } |
| | | } |
| | | |
| | | class DialogUtil { |
| | | static Future<dynamic> showDialog(BuildContext context, Dialog dialog) async { |
| | | return await showGeneralDialog( |
| | | context: context, |
| | | pageBuilder: (BuildContext buildContext, Animation<double> animation, |
| | | Animation<double> secondaryAnimation) { |
| | | return dialog; |
| | | }); |
| | | } |
| | | } |
| | | |
| | | class DimenUtil { |
| | | //获取像素比 |
| | | static double getPixelRatio(BuildContext context) { |
| | | MediaQueryData mediaQuery = MediaQuery.of(context); |
| | | return mediaQuery.devicePixelRatio; |
| | | } |
| | | } |
New file |
| | |
| | | import 'dart:async'; |
| | | import 'dart:convert'; |
| | | import 'dart:ui'; |
| | | |
| | | import 'package:flutter/cupertino.dart'; |
| | | import 'package:flutter/services.dart'; |
| | | import 'package:fluwx_no_pay/fluwx_no_pay.dart' as fluwx; |
| | | import '../api/http.dart'; |
| | | import '../model/user/user_info.dart'; |
| | | import '../utils/event_bus_util.dart'; |
| | | import '../utils/string_util.dart'; |
| | | import 'package:shared_preferences/shared_preferences.dart'; |
| | | |
| | | import 'push_util.dart'; |
| | | |
| | | Timer? locationTimer; |
| | | |
| | | class UserUtil { |
| | | static const _loginMessageChannel = |
| | | BasicMessageChannel('ThirdLogin', StandardMessageCodec()); |
| | | |
| | | //是否同意了用户协议 |
| | | static Future<bool> isAgreeProtocol() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | bool? agree = prefs.getBool("agree_protocol"); |
| | | if (agree == null) { |
| | | return false; |
| | | } |
| | | return agree; |
| | | } |
| | | |
| | | //设置已同意用户协议 |
| | | static Future<bool> setAgreeProtocol() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | return prefs.setBool("agree_protocol", true); |
| | | } |
| | | |
| | | ///微信登录 |
| | | static void loginWX() async { |
| | | fluwx |
| | | .sendWeChatAuth(scope: "snsapi_userinfo", state: "wechat_sdk_demo_test") |
| | | .then((value) {}); |
| | | } |
| | | |
| | | ///QQ登录 |
| | | static Future<Map> loginQQ() async { |
| | | Map value = await _loginMessageChannel.send({"method": "loginQQ"}) as Map; |
| | | return value; |
| | | } |
| | | |
| | | //是否已经登录 |
| | | static Future<bool> isLogin() async { |
| | | UserInfo? user = await getUserInfo(); |
| | | return user != null; |
| | | } |
| | | |
| | | //用户信息 |
| | | static Future<UserInfo?> getUserInfo() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | String? result = await prefs.getString("user_info"); |
| | | if (StringUtil.isNullOrEmpty(result)) { |
| | | return null; |
| | | } else { |
| | | return UserInfo.fromJson(jsonDecode(result!)); |
| | | } |
| | | } |
| | | |
| | | static Future updateUserInfo(BuildContext context) async { |
| | | int? uid = await getUid(); |
| | | if (uid == null) { |
| | | return; |
| | | } |
| | | |
| | | Map<String, dynamic>? result = await UserApiUtil.getUserInfo(context, uid); |
| | | var code = result!["code"]; |
| | | if (code == 0) { |
| | | UserInfo user = UserInfo.fromJson(result["data"]); |
| | | //保存用户信息 |
| | | UserUtil.setUserInfo(user); |
| | | } else if (code == 80001 || code == 80002) { |
| | | await logout(); |
| | | } |
| | | } |
| | | |
| | | static Future<int?> getUid() async { |
| | | UserInfo? user = await getUserInfo(); |
| | | if (user != null) { |
| | | return user.id; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | static Future setUserInfo(UserInfo user) async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | await prefs.setString("user_info", jsonEncode(user)); |
| | | } |
| | | |
| | | //退出登录 |
| | | static logout() async { |
| | | await _logout(); |
| | | await PushUtil.removeAlias(); |
| | | eventBus.fire(LoginEventBus(false)); |
| | | } |
| | | |
| | | static _logout() async { |
| | | SharedPreferences prefs = await SharedPreferences.getInstance(); |
| | | prefs.remove("user_info"); |
| | | } |
| | | } |
New file |
| | |
| | | # Generated by pub |
| | | # See https://dart.dev/tools/pub/glossary#lockfile |
| | | packages: |
| | | async: |
| | | dependency: transitive |
| | | description: |
| | | name: async |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.8.1" |
| | | boolean_selector: |
| | | dependency: transitive |
| | | description: |
| | | name: boolean_selector |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.0" |
| | | characters: |
| | | dependency: transitive |
| | | description: |
| | | name: characters |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.0" |
| | | charcode: |
| | | dependency: transitive |
| | | description: |
| | | name: charcode |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.3.1" |
| | | clock: |
| | | dependency: transitive |
| | | description: |
| | | name: clock |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.0" |
| | | collection: |
| | | dependency: transitive |
| | | description: |
| | | name: collection |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.15.0" |
| | | crypto: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: crypto |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.1" |
| | | csslib: |
| | | dependency: transitive |
| | | description: |
| | | name: csslib |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.17.1" |
| | | cupertino_icons: |
| | | dependency: "direct main" |
| | | description: |
| | | name: cupertino_icons |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.0.4" |
| | | date_format: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: date_format |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.5" |
| | | device_info: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: device_info |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.3" |
| | | device_info_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: device_info_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.1" |
| | | dio: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: dio |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "4.0.4" |
| | | event_bus: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: event_bus |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.0" |
| | | fake_async: |
| | | dependency: transitive |
| | | description: |
| | | name: fake_async |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.2.0" |
| | | ffi: |
| | | dependency: transitive |
| | | description: |
| | | name: ffi |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.2" |
| | | file: |
| | | dependency: transitive |
| | | description: |
| | | name: file |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "6.1.2" |
| | | flutter: |
| | | dependency: "direct main" |
| | | description: flutter |
| | | source: sdk |
| | | version: "0.0.0" |
| | | flutter_datetime_picker: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_datetime_picker |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.5.1" |
| | | flutter_lints: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_lints |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.0.4" |
| | | flutter_page_indicator: |
| | | dependency: transitive |
| | | description: |
| | | name: flutter_page_indicator |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.0.3" |
| | | flutter_spinkit: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_spinkit |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "5.1.0" |
| | | flutter_swiper: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_swiper |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.6" |
| | | flutter_tencentad: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_tencentad |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.4" |
| | | flutter_test: |
| | | dependency: "direct dev" |
| | | description: flutter |
| | | source: sdk |
| | | version: "0.0.0" |
| | | flutter_unionad: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_unionad |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.2.2" |
| | | flutter_web_plugins: |
| | | dependency: transitive |
| | | description: flutter |
| | | source: sdk |
| | | version: "0.0.0" |
| | | flutter_widget_from_html_core: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: flutter_widget_from_html_core |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.8.4" |
| | | fluttertoast: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: fluttertoast |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "8.0.8" |
| | | fluwx_no_pay: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: fluwx_no_pay |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.6.1+5" |
| | | fwfh_text_style: |
| | | dependency: transitive |
| | | description: |
| | | name: fwfh_text_style |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.5.1" |
| | | html: |
| | | dependency: transitive |
| | | description: |
| | | name: html |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.15.0" |
| | | http_parser: |
| | | dependency: transitive |
| | | description: |
| | | name: http_parser |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "4.0.0" |
| | | jpush_flutter: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: jpush_flutter |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.2.2" |
| | | js: |
| | | dependency: transitive |
| | | description: |
| | | name: js |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.6.3" |
| | | launch_review: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: launch_review |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.1" |
| | | lints: |
| | | dependency: transitive |
| | | description: |
| | | name: lints |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.0.1" |
| | | matcher: |
| | | dependency: transitive |
| | | description: |
| | | name: matcher |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.12.10" |
| | | meta: |
| | | dependency: transitive |
| | | description: |
| | | name: meta |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.7.0" |
| | | mime: |
| | | dependency: transitive |
| | | description: |
| | | name: mime |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.0.1" |
| | | package_info: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: package_info |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | path: |
| | | dependency: transitive |
| | | description: |
| | | name: path |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.8.0" |
| | | path_provider: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: path_provider |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.8" |
| | | path_provider_android: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_android |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.11" |
| | | path_provider_ios: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_ios |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.7" |
| | | path_provider_linux: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_linux |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.5" |
| | | path_provider_macos: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_macos |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.5" |
| | | path_provider_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.3" |
| | | path_provider_windows: |
| | | dependency: transitive |
| | | description: |
| | | name: path_provider_windows |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.5" |
| | | permission_handler: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: permission_handler |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "8.3.0" |
| | | permission_handler_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: permission_handler_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.7.0" |
| | | platform: |
| | | dependency: transitive |
| | | description: |
| | | name: platform |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.1.0" |
| | | plugin_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: plugin_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.2" |
| | | process: |
| | | dependency: transitive |
| | | description: |
| | | name: process |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "4.2.4" |
| | | pull_to_refresh: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: pull_to_refresh |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.0" |
| | | qr: |
| | | dependency: transitive |
| | | description: |
| | | name: qr |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.0" |
| | | qr_flutter: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: qr_flutter |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "4.0.0" |
| | | screenshot: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: screenshot |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.2.3" |
| | | share_plus: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: share_plus |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.4" |
| | | share_plus_linux: |
| | | dependency: transitive |
| | | description: |
| | | name: share_plus_linux |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.4" |
| | | share_plus_macos: |
| | | dependency: transitive |
| | | description: |
| | | name: share_plus_macos |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | share_plus_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: share_plus_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.1" |
| | | share_plus_web: |
| | | dependency: transitive |
| | | description: |
| | | name: share_plus_web |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.4" |
| | | share_plus_windows: |
| | | dependency: transitive |
| | | description: |
| | | name: share_plus_windows |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.3" |
| | | shared_preferences: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: shared_preferences |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.12" |
| | | shared_preferences_android: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_android |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.10" |
| | | shared_preferences_ios: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_ios |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.9" |
| | | shared_preferences_linux: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_linux |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.4" |
| | | shared_preferences_macos: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_macos |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | shared_preferences_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.0" |
| | | shared_preferences_web: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_web |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.3" |
| | | shared_preferences_windows: |
| | | dependency: transitive |
| | | description: |
| | | name: shared_preferences_windows |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.4" |
| | | sky_engine: |
| | | dependency: transitive |
| | | description: flutter |
| | | source: sdk |
| | | version: "0.0.99" |
| | | source_span: |
| | | dependency: transitive |
| | | description: |
| | | name: source_span |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.8.1" |
| | | sqflite: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: sqflite |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | sqflite_common: |
| | | dependency: transitive |
| | | description: |
| | | name: sqflite_common |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.1+1" |
| | | stack_trace: |
| | | dependency: transitive |
| | | description: |
| | | name: stack_trace |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.10.0" |
| | | stream_channel: |
| | | dependency: transitive |
| | | description: |
| | | name: stream_channel |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.0" |
| | | string_scanner: |
| | | dependency: transitive |
| | | description: |
| | | name: string_scanner |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.1.0" |
| | | synchronized: |
| | | dependency: transitive |
| | | description: |
| | | name: synchronized |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "3.0.0" |
| | | term_glyph: |
| | | dependency: transitive |
| | | description: |
| | | name: term_glyph |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.2.0" |
| | | test_api: |
| | | dependency: transitive |
| | | description: |
| | | name: test_api |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.4.2" |
| | | transformer_page_view: |
| | | dependency: transitive |
| | | description: |
| | | name: transformer_page_view |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.1.6" |
| | | typed_data: |
| | | dependency: transitive |
| | | description: |
| | | name: typed_data |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.3.0" |
| | | url_launcher: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: url_launcher |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "6.0.18" |
| | | url_launcher_android: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_android |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "6.0.14" |
| | | url_launcher_ios: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_ios |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "6.0.14" |
| | | url_launcher_linux: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_linux |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.3" |
| | | url_launcher_macos: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_macos |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | url_launcher_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.5" |
| | | url_launcher_web: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_web |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.6" |
| | | url_launcher_windows: |
| | | dependency: transitive |
| | | description: |
| | | name: url_launcher_windows |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.0.2" |
| | | vector_math: |
| | | dependency: transitive |
| | | description: |
| | | name: vector_math |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.1.0" |
| | | webview_flutter: |
| | | dependency: "direct dev" |
| | | description: |
| | | name: webview_flutter |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.8.0" |
| | | webview_flutter_android: |
| | | dependency: transitive |
| | | description: |
| | | name: webview_flutter_android |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.8.2" |
| | | webview_flutter_platform_interface: |
| | | dependency: transitive |
| | | description: |
| | | name: webview_flutter_platform_interface |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "1.8.1" |
| | | webview_flutter_wkwebview: |
| | | dependency: transitive |
| | | description: |
| | | name: webview_flutter_wkwebview |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.7.1" |
| | | win32: |
| | | dependency: transitive |
| | | description: |
| | | name: win32 |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "2.3.6" |
| | | xdg_directories: |
| | | dependency: transitive |
| | | description: |
| | | name: xdg_directories |
| | | url: "https://pub.flutter-io.cn" |
| | | source: hosted |
| | | version: "0.2.0" |
| | | sdks: |
| | | dart: ">=2.14.0 <3.0.0" |
| | | flutter: ">=2.5.0" |
New file |
| | |
| | | name: hanju |
| | | description: A new Flutter project. |
| | | |
| | | # The following line prevents the package from being accidentally published to |
| | | # pub.dev using `flutter pub publish`. This is preferred for private packages. |
| | | publish_to: 'none' # Remove this line if you wish to publish to pub.dev |
| | | |
| | | # The following defines the version and build number for your application. |
| | | # A version number is three numbers separated by dots, like 1.2.43 |
| | | # followed by an optional build number separated by a +. |
| | | # Both the version and the builder number may be overridden in flutter |
| | | # build by specifying --build-name and --build-number, respectively. |
| | | # In Android, build-name is used as versionName while build-number used as versionCode. |
| | | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning |
| | | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. |
| | | # Read more about iOS versioning at |
| | | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html |
| | | version: 1.0.0+1 |
| | | |
| | | environment: |
| | | sdk: ">=2.12.0 <3.0.0" |
| | | |
| | | # Dependencies specify other packages that your package needs in order to work. |
| | | # To automatically upgrade your package dependencies to the latest versions |
| | | # consider running `flutter pub upgrade --major-versions`. Alternatively, |
| | | # dependencies can be manually updated by changing the version numbers below to |
| | | # the latest version available on pub.dev. To see which dependencies have newer |
| | | # versions available, run `flutter pub outdated`. |
| | | dependencies: |
| | | flutter: |
| | | sdk: flutter |
| | | |
| | | |
| | | # The following adds the Cupertino Icons font to your application. |
| | | # Use with the CupertinoIcons class for iOS style icons. |
| | | cupertino_icons: ^1.0.2 |
| | | |
| | | dev_dependencies: |
| | | flutter_test: |
| | | sdk: flutter |
| | | |
| | | # The "flutter_lints" package below contains a set of recommended lints to |
| | | # encourage good coding practices. The lint set provided by the package is |
| | | # activated in the `analysis_options.yaml` file located at the root of your |
| | | # package. See that file for information about deactivating specific lint |
| | | # rules and activating additional ones. |
| | | flutter_lints: ^1.0.0 |
| | | cupertino_icons: ^1.0.3 |
| | | permission_handler: ^8.2.6 |
| | | |
| | | |
| | | shared_preferences: ^2.0.8 |
| | | |
| | | sqflite: ^2.0.0+3 |
| | | |
| | | dio: ^4.0.0 |
| | | |
| | | #轮播图插件 |
| | | flutter_swiper: ^1.1.6 |
| | | |
| | | fluttertoast: ^8.0.8 |
| | | |
| | | webview_flutter: ^2.8.0 |
| | | |
| | | #穿山甲广告 |
| | | flutter_unionad: ^1.1.9 |
| | | #广点通广告 |
| | | flutter_tencentad: ^1.1.0 |
| | | flutter_widget_from_html_core: ^0.8.3 |
| | | |
| | | #时间日期选择 |
| | | flutter_datetime_picker: ^1.5.1 |
| | | #二维码生成 |
| | | qr_flutter: ^4.0.0 |
| | | |
| | | #分享组件 |
| | | share_plus: ^3.0.4 |
| | | path_provider: ^2.0.6 |
| | | |
| | | #微信登录 |
| | | fluwx_no_pay: ^3.6.1+5 |
| | | |
| | | event_bus: ^2.0.0 |
| | | |
| | | #极光推送 |
| | | jpush_flutter: ^2.1.8 |
| | | |
| | | #获取设备信息 |
| | | device_info: ^2.0.3 |
| | | |
| | | #加密 |
| | | crypto: ^3.0.1 |
| | | |
| | | flutter_spinkit: ^5.1.0 |
| | | |
| | | #下拉刷新 |
| | | pull_to_refresh: ^2.0.0 |
| | | |
| | | url_launcher: ^6.0.17 |
| | | |
| | | package_info: ^2.0.2 |
| | | |
| | | launch_review: ^3.0.1 |
| | | |
| | | date_format: ^2.0.4 |
| | | |
| | | #截图插件 |
| | | screenshot: ^1.2.3 |
| | | |
| | | # For information on the generic Dart part of this file, see the |
| | | # following page: https://dart.dev/tools/pub/pubspec |
| | | |
| | | # The following section is specific to Flutter. |
| | | flutter: |
| | | |
| | | # The following line ensures that the Material Icons font is |
| | | # included with your application, so that you can use the icons in |
| | | # the material Icons class. |
| | | uses-material-design: true |
| | | assets: |
| | | - assets/imgs/ |
| | | |
| | | # To add assets to your application, add an assets section, like this: |
| | | # assets: |
| | | # - images/a_dot_burr.jpeg |
| | | # - images/a_dot_ham.jpeg |
| | | |
| | | # An image asset can refer to one or more resolution-specific "variants", see |
| | | # https://flutter.dev/assets-and-images/#resolution-aware. |
| | | |
| | | # For details regarding adding assets from package dependencies, see |
| | | # https://flutter.dev/assets-and-images/#from-packages |
| | | |
| | | # To add custom fonts to your application, add a fonts section here, |
| | | # in this "flutter" section. Each entry in this list should have a |
| | | # "family" key with the font family name, and a "fonts" key with a |
| | | # list giving the asset and other descriptors for the font. For |
| | | # example: |
| | | # fonts: |
| | | # - family: Schyler |
| | | # fonts: |
| | | # - asset: fonts/Schyler-Regular.ttf |
| | | # - asset: fonts/Schyler-Italic.ttf |
| | | # style: italic |
| | | # - family: Trajan Pro |
| | | # fonts: |
| | | # - asset: fonts/TrajanPro.ttf |
| | | # - asset: fonts/TrajanPro_Bold.ttf |
| | | # weight: 700 |
| | | # |
| | | # For details regarding fonts from package dependencies, |
| | | # see https://flutter.dev/custom-fonts/#from-packages |
New file |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <!-- |
| | | If you are serving your web app in a path other than the root, change the |
| | | href value below to reflect the base path you are serving from. |
| | | |
| | | The path provided below has to start and end with a slash "/" in order for |
| | | it to work correctly. |
| | | |
| | | For more details: |
| | | * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base |
| | | |
| | | This is a placeholder for base href that will be replaced by the value of |
| | | the `--base-href` argument provided to `flutter build`. |
| | | --> |
| | | <base href="$FLUTTER_BASE_HREF"> |
| | | |
| | | <meta charset="UTF-8"> |
| | | <meta content="IE=Edge" http-equiv="X-UA-Compatible"> |
| | | <meta name="description" content="A new Flutter project."> |
| | | |
| | | <!-- iOS meta tags & icons --> |
| | | <meta name="apple-mobile-web-app-capable" content="yes"> |
| | | <meta name="apple-mobile-web-app-status-bar-style" content="black"> |
| | | <meta name="apple-mobile-web-app-title" content="hanju"> |
| | | <link rel="apple-touch-icon" href="icons/Icon-192.png"> |
| | | |
| | | <title>hanju</title> |
| | | <link rel="manifest" href="manifest.json"> |
| | | </head> |
| | | <body> |
| | | <!-- This script installs service_worker.js to provide PWA functionality to |
| | | application. For more information, see: |
| | | https://developers.google.com/web/fundamentals/primers/service-workers --> |
| | | <script> |
| | | var serviceWorkerVersion = null; |
| | | var scriptLoaded = false; |
| | | function loadMainDartJs() { |
| | | if (scriptLoaded) { |
| | | return; |
| | | } |
| | | scriptLoaded = true; |
| | | var scriptTag = document.createElement('script'); |
| | | scriptTag.src = 'main.dart.js'; |
| | | scriptTag.type = 'application/javascript'; |
| | | document.body.append(scriptTag); |
| | | } |
| | | |
| | | if ('serviceWorker' in navigator) { |
| | | // Service workers are supported. Use them. |
| | | window.addEventListener('load', function () { |
| | | // Wait for registration to finish before dropping the <script> tag. |
| | | // Otherwise, the browser will load the script multiple times, |
| | | // potentially different versions. |
| | | var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion; |
| | | navigator.serviceWorker.register(serviceWorkerUrl) |
| | | .then((reg) => { |
| | | function waitForActivation(serviceWorker) { |
| | | serviceWorker.addEventListener('statechange', () => { |
| | | if (serviceWorker.state == 'activated') { |
| | | console.log('Installed new service worker.'); |
| | | loadMainDartJs(); |
| | | } |
| | | }); |
| | | } |
| | | if (!reg.active && (reg.installing || reg.waiting)) { |
| | | // No active web worker and we have installed or are installing |
| | | // one for the first time. Simply wait for it to activate. |
| | | waitForActivation(reg.installing || reg.waiting); |
| | | } else if (!reg.active.scriptURL.endsWith(serviceWorkerVersion)) { |
| | | // When the app updates the serviceWorkerVersion changes, so we |
| | | // need to ask the service worker to update. |
| | | console.log('New service worker available.'); |
| | | reg.update(); |
| | | waitForActivation(reg.installing); |
| | | } else { |
| | | // Existing service worker is still good. |
| | | console.log('Loading app from service worker.'); |
| | | loadMainDartJs(); |
| | | } |
| | | }); |
| | | |
| | | // If service worker doesn't succeed in a reasonable amount of time, |
| | | // fallback to plaint <script> tag. |
| | | setTimeout(() => { |
| | | if (!scriptLoaded) { |
| | | console.warn( |
| | | 'Failed to load app from service worker. Falling back to plain <script> tag.', |
| | | ); |
| | | loadMainDartJs(); |
| | | } |
| | | }, 4000); |
| | | }); |
| | | } else { |
| | | // Service workers not supported. Just drop the <script> tag. |
| | | loadMainDartJs(); |
| | | } |
| | | </script> |
| | | </body> |
| | | </html> |
New file |
| | |
| | | { |
| | | "name": "hanju", |
| | | "short_name": "hanju", |
| | | "start_url": ".", |
| | | "display": "standalone", |
| | | "background_color": "#0175C2", |
| | | "theme_color": "#0175C2", |
| | | "description": "A new Flutter project.", |
| | | "orientation": "portrait-primary", |
| | | "prefer_related_applications": false, |
| | | "icons": [ |
| | | { |
| | | "src": "icons/Icon-192.png", |
| | | "sizes": "192x192", |
| | | "type": "image/png" |
| | | }, |
| | | { |
| | | "src": "icons/Icon-512.png", |
| | | "sizes": "512x512", |
| | | "type": "image/png" |
| | | }, |
| | | { |
| | | "src": "icons/Icon-maskable-192.png", |
| | | "sizes": "192x192", |
| | | "type": "image/png", |
| | | "purpose": "maskable" |
| | | }, |
| | | { |
| | | "src": "icons/Icon-maskable-512.png", |
| | | "sizes": "512x512", |
| | | "type": "image/png", |
| | | "purpose": "maskable" |
| | | } |
| | | ] |
| | | } |