├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── build.yml
├── .gitignore
├── .vscode
├── build.sh
└── launch.json
├── LICENSE
├── README.md
├── README_ZH.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── m
│ │ │ │ └── c
│ │ │ │ └── g
│ │ │ │ └── a
│ │ │ │ └── i_iwara
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-hdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-mdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-xxhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable-xxxhdpi
│ │ │ └── ic_launcher_foreground.png
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ └── launcher_icon.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── launcher_icon.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ ├── colors.xml
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
├── icon
│ └── launcher_icon_v2.png
├── images
│ ├── 2.0x
│ │ └── flutter_logo.png
│ ├── 3.0x
│ │ └── flutter_logo.png
│ └── flutter_logo.png
└── svg
│ ├── app_enter_fullscreen.svg
│ └── app_exit_fullscreen.svg
├── docs
└── imgs
│ ├── all.png
│ ├── dingyue.png
│ ├── download.png
│ ├── filter.png
│ ├── gonggao.png
│ ├── huihua.png
│ ├── localshoucang.png
│ ├── luntan.png
│ ├── luntanxaingqing.png
│ ├── pinglun.png
│ ├── record.png
│ ├── shezhi.png
│ ├── shipin.png
│ ├── shipin2.png
│ ├── shipinliebiao.png
│ ├── sousuo.png
│ ├── tongzhi.png
│ ├── tuku.png
│ ├── tukuliebiao.png
│ └── zuozhe.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-50x50@1x.png
│ │ │ ├── Icon-App-50x50@2x.png
│ │ │ ├── Icon-App-57x57@1x.png
│ │ │ ├── Icon-App-57x57@2x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-72x72@1x.png
│ │ │ ├── Icon-App-72x72@2x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
└── RunnerTests
│ └── RunnerTests.swift
├── lib
├── app
│ ├── models
│ │ ├── api_result.model.dart
│ │ ├── captcha.model.dart
│ │ ├── comment.model.dart
│ │ ├── custom_thumbnail.model.dart
│ │ ├── download
│ │ │ ├── download_task.model.dart
│ │ │ └── download_task_ext_data.model.dart
│ │ ├── dto
│ │ │ ├── escape_intent.dart
│ │ │ ├── forum_thread_section_dto.dart
│ │ │ ├── history_record_dto.dart
│ │ │ ├── profile_user_dto.dart
│ │ │ ├── user_dto.dart
│ │ │ └── user_request_dto.dart
│ │ ├── favorite
│ │ │ ├── favorite_folder.model.dart
│ │ │ └── favorite_item.model.dart
│ │ ├── forum.model.dart
│ │ ├── history_record.dart
│ │ ├── image.model.dart
│ │ ├── light_play_list.model.dart
│ │ ├── media_file.model.dart
│ │ ├── message_and_conversation.model.dart
│ │ ├── page_data.model.dart
│ │ ├── play_list.model.dart
│ │ ├── post.model.dart
│ │ ├── rules.model.dart
│ │ ├── search_record.model.dart
│ │ ├── sort.model.dart
│ │ ├── tag.model.dart
│ │ ├── theme_mode.model.dart
│ │ ├── update_info.model.dart
│ │ ├── user.model.dart
│ │ ├── user_avatar.model.dart
│ │ ├── user_notification_count.model.dart
│ │ ├── video.model.dart
│ │ └── video_source.model.dart
│ ├── my_app.dart
│ ├── repositories
│ │ ├── base_repository.dart
│ │ ├── commons_repository.dart
│ │ ├── download_task_repository.dart
│ │ ├── history_repository.dart
│ │ └── sign_in_repository.dart
│ ├── routes
│ │ └── app_routes.dart
│ ├── services
│ │ ├── api_service.dart
│ │ ├── app_service.dart
│ │ ├── auth_service.dart
│ │ ├── comment_service.dart
│ │ ├── config_backup_service.dart
│ │ ├── config_service.dart
│ │ ├── conversation_service.dart
│ │ ├── deep_link_service.dart
│ │ ├── download_service.dart
│ │ ├── favorite_service.dart
│ │ ├── forum_service.dart
│ │ ├── gallery_service.dart
│ │ ├── light_service.dart
│ │ ├── log_service.dart
│ │ ├── message_service.dart
│ │ ├── play_list_service.dart
│ │ ├── playback_history_service.dart
│ │ ├── post_service.dart
│ │ ├── search_service.dart
│ │ ├── share_service.dart
│ │ ├── storage_service.dart
│ │ ├── tag_service.dart
│ │ ├── theme_service.dart
│ │ ├── translation_service.dart
│ │ ├── user_preference_service.dart
│ │ ├── user_service.dart
│ │ ├── version_service.dart
│ │ └── video_service.dart
│ ├── ui
│ │ ├── pages
│ │ │ ├── author_profile
│ │ │ │ ├── author_profile_page.dart
│ │ │ │ ├── controllers
│ │ │ │ │ ├── authro_profile_controller.dart
│ │ │ │ │ ├── userz_image_model_list_controller.dart
│ │ │ │ │ ├── userz_post_list_repository.dart
│ │ │ │ │ └── userz_video_list_controller.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── author_profile_skeleton_widget.dart
│ │ │ │ │ ├── post_input_dialog.dart
│ │ │ │ │ ├── profile_image_model_tab_list_widget.dart
│ │ │ │ │ ├── profile_playlist_tab_list_widget.dart
│ │ │ │ │ ├── profile_post_tab_list_widget.dart
│ │ │ │ │ ├── profile_video_tab_list_widget.dart
│ │ │ │ │ └── share_user_bottom_sheet.dart
│ │ │ ├── comment
│ │ │ │ ├── controllers
│ │ │ │ │ └── comment_controller.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── comment_entry_area_widget.dart
│ │ │ │ │ ├── comment_input_dialog.dart
│ │ │ │ │ ├── comment_item_widget.dart
│ │ │ │ │ ├── comment_remove_dialog.dart
│ │ │ │ │ ├── comment_section_widget.dart
│ │ │ │ │ └── rules_agreement_dialog_widget.dart
│ │ │ ├── conversation
│ │ │ │ ├── controllers
│ │ │ │ │ └── conversation_list_repository.dart
│ │ │ │ ├── conversation_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── conversation_list_widget.dart
│ │ │ │ │ ├── conversation_message_dialog.dart
│ │ │ │ │ ├── message_list_widget.dart
│ │ │ │ │ └── new_conversation_dialog.dart
│ │ │ ├── download
│ │ │ │ ├── download_task_list_page.dart
│ │ │ │ ├── gallery_download_task_detail_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── default_download_task_item_widget.dart
│ │ │ │ │ ├── gallery_download_task_item_widget.dart
│ │ │ │ │ ├── status_label_widget.dart
│ │ │ │ │ └── video_download_task_item_widget.dart
│ │ │ ├── favorite
│ │ │ │ ├── favorite_folder_detail_page.dart
│ │ │ │ └── favorite_list_page.dart
│ │ │ ├── favorites
│ │ │ │ ├── controllers
│ │ │ │ │ └── favorites_controller.dart
│ │ │ │ ├── my_favorites.dart
│ │ │ │ ├── repositories
│ │ │ │ │ ├── favorite_image_repository.dart
│ │ │ │ │ └── favorite_video_repository.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── favorite_image_list.dart
│ │ │ │ │ └── favorite_video_list.dart
│ │ │ ├── follows
│ │ │ │ ├── controllers
│ │ │ │ │ └── follows_controller.dart
│ │ │ │ ├── follows_page.dart
│ │ │ │ ├── repositories
│ │ │ │ │ ├── followers_list_repository.dart
│ │ │ │ │ └── following_list_repository.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── followers_list.dart
│ │ │ │ │ ├── following_list.dart
│ │ │ │ │ └── special_follows_list.dart
│ │ │ ├── forum
│ │ │ │ ├── controllers
│ │ │ │ │ ├── forum_list_controller.dart
│ │ │ │ │ ├── recent_thread_repository.dart
│ │ │ │ │ ├── thread_detail_repository.dart
│ │ │ │ │ └── thread_list_repository.dart
│ │ │ │ ├── forum_page.dart
│ │ │ │ ├── forum_skeleton_page.dart
│ │ │ │ ├── thread_detail_page.dart
│ │ │ │ ├── thread_list_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── forum_edit_reply_dialog.dart
│ │ │ │ │ ├── forum_edit_title_dialog.dart
│ │ │ │ │ ├── forum_post_dialog.dart
│ │ │ │ │ ├── forum_reply_dialog.dart
│ │ │ │ │ ├── forum_shimmer_widget.dart
│ │ │ │ │ ├── share_thread_bottom_sheet.dart
│ │ │ │ │ ├── thread_comment_card_widget.dart
│ │ │ │ │ └── thread_list_item_widget.dart
│ │ │ ├── friends
│ │ │ │ ├── controllers
│ │ │ │ │ └── friends_controller.dart
│ │ │ │ ├── friends_page.dart
│ │ │ │ ├── repositories
│ │ │ │ │ ├── friend_list_repository.dart
│ │ │ │ │ └── friend_request_repository.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── friend_list.dart
│ │ │ │ │ └── friend_request_list.dart
│ │ │ ├── gallery_detail
│ │ │ │ ├── controllers
│ │ │ │ │ └── gallery_detail_controller.dart
│ │ │ │ ├── gallery_detail_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── gallery_image_scroller_widget.dart
│ │ │ │ │ ├── horizontial_image_list.dart
│ │ │ │ │ ├── image_model_detail_content_widget.dart
│ │ │ │ │ ├── menu_item_widget.dart
│ │ │ │ │ ├── my_gallery_photo_view_wrapper.dart
│ │ │ │ │ └── share_gallery_bottom_sheet.dart
│ │ │ ├── history
│ │ │ │ ├── controllers
│ │ │ │ │ ├── history_list_controller.dart
│ │ │ │ │ └── history_list_repository.dart
│ │ │ │ └── history_list_page.dart
│ │ │ ├── home
│ │ │ │ └── home_navigation_layout.dart
│ │ │ ├── home_page.dart
│ │ │ ├── login
│ │ │ │ └── login_page.dart
│ │ │ ├── notifications
│ │ │ │ ├── controllers
│ │ │ │ │ └── notification_list_repository.dart
│ │ │ │ ├── notification_list_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── notification_content_items.dart
│ │ │ │ │ └── notification_list_item_widget.dart
│ │ │ ├── play_list
│ │ │ │ ├── controllers
│ │ │ │ │ ├── play_list_controller.dart
│ │ │ │ │ ├── play_list_detail_controller.dart
│ │ │ │ │ ├── play_list_detail_repository.dart
│ │ │ │ │ └── play_list_repository.dart
│ │ │ │ ├── play_list.dart
│ │ │ │ ├── play_list_detail.dart
│ │ │ │ └── widgets
│ │ │ │ │ └── playlist_item_widget.dart
│ │ │ ├── popular_media_list
│ │ │ │ ├── controllers
│ │ │ │ │ ├── base_media_controller.dart
│ │ │ │ │ ├── base_media_repository.dart
│ │ │ │ │ ├── popular_gallery_controller.dart
│ │ │ │ │ ├── popular_gallery_repository.dart
│ │ │ │ │ ├── popular_media_list_controller.dart
│ │ │ │ │ ├── popular_video_controller.dart
│ │ │ │ │ ├── popular_video_repository.dart
│ │ │ │ │ └── tag_controller.dart
│ │ │ │ ├── popular_gallery_list_page.dart
│ │ │ │ ├── popular_media_list_base_page.dart
│ │ │ │ ├── popular_video_list_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── add_search_tag_dialog.dart
│ │ │ │ │ ├── animated_preview_widget.dart
│ │ │ │ │ ├── common_media_list_widgets.dart
│ │ │ │ │ ├── image_model_card_list_item_widget.dart
│ │ │ │ │ ├── image_model_tile_list_item_widget.dart
│ │ │ │ │ ├── media_description_widget.dart
│ │ │ │ │ ├── media_list_view.dart
│ │ │ │ │ ├── media_tab_view.dart
│ │ │ │ │ ├── popular_media_search_config_widget.dart
│ │ │ │ │ ├── post_card_list_item_widget.dart
│ │ │ │ │ ├── post_tile_list_item_widget.dart
│ │ │ │ │ ├── remove_search_tag_dialog.dart
│ │ │ │ │ ├── video_card_list_item_widget.dart
│ │ │ │ │ ├── video_preview_modal.dart
│ │ │ │ │ └── video_tile_list_item_widget.dart
│ │ │ ├── post_detail
│ │ │ │ ├── controllers
│ │ │ │ │ └── post_detail_controller.dart
│ │ │ │ ├── post_detail_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── post_detail_content_widget.dart
│ │ │ │ │ ├── post_detail_shimmer.dart
│ │ │ │ │ └── share_post_bottom_sheet.dart
│ │ │ ├── search
│ │ │ │ ├── repositories
│ │ │ │ │ ├── search_repositories.dart
│ │ │ │ │ └── search_repository.dart
│ │ │ │ ├── search_dialog.dart
│ │ │ │ ├── search_result.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── base_search_list.dart
│ │ │ │ │ └── search_list_widgets.dart
│ │ │ ├── settings
│ │ │ │ ├── about_page.dart
│ │ │ │ ├── app_settings_page.dart
│ │ │ │ ├── history_update_logs_page.dart
│ │ │ │ ├── player_settings_page.dart
│ │ │ │ ├── proxy_settings_page.dart
│ │ │ │ ├── settings_page.dart
│ │ │ │ ├── theme_settings_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── ai_translation_setting_widget.dart
│ │ │ │ │ ├── player_settings_widget.dart
│ │ │ │ │ ├── proxy_setting_widget.dart
│ │ │ │ │ ├── setting_item_widget.dart
│ │ │ │ │ ├── settings_app_bar.dart
│ │ │ │ │ ├── signature_edit_dialog_widget.dart
│ │ │ │ │ └── three_section_slider.dart
│ │ │ ├── sign_in
│ │ │ │ ├── controllers
│ │ │ │ │ └── sign_in_controller.dart
│ │ │ │ ├── sing_in_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ └── sign_in_heatmap_widget.dart
│ │ │ ├── splash
│ │ │ │ └── splash_page.dart
│ │ │ ├── subscriptions
│ │ │ │ ├── controllers
│ │ │ │ │ ├── media_list_controller.dart
│ │ │ │ │ ├── subscription_image_repository.dart
│ │ │ │ │ ├── subscription_post_repository.dart
│ │ │ │ │ └── subscription_video_repository.dart
│ │ │ │ ├── subscriptions_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ ├── base_subscription_list.dart
│ │ │ │ │ ├── compact_subscription_dropdown.dart
│ │ │ │ │ ├── subscription_image_list.dart
│ │ │ │ │ ├── subscription_post_list.dart
│ │ │ │ │ ├── subscription_select_list_widget.dart
│ │ │ │ │ └── subscription_video_list.dart
│ │ │ ├── tag_blacklist
│ │ │ │ ├── controllers
│ │ │ │ │ └── tag_blacklist_controller.dart
│ │ │ │ ├── tag_blacklist_page.dart
│ │ │ │ └── widgets
│ │ │ │ │ └── black_list_search_tag_dialog.dart
│ │ │ └── video_detail
│ │ │ │ ├── controllers
│ │ │ │ ├── my_video_state_controller.dart
│ │ │ │ └── related_media_controller.dart
│ │ │ │ ├── video_detail_page_v2.dart
│ │ │ │ └── widgets
│ │ │ │ ├── comment_entry_area_widget.dart
│ │ │ │ ├── detail
│ │ │ │ ├── add_video_to_playlist_dialog.dart
│ │ │ │ ├── expandable_tags_widget.dart
│ │ │ │ ├── like_avatars_widget.dart
│ │ │ │ ├── share_video_bottom_sheet.dart
│ │ │ │ ├── video_description_widget.dart
│ │ │ │ └── video_detail_content_widget.dart
│ │ │ │ ├── media_tile_list_loading_widget.dart
│ │ │ │ ├── player
│ │ │ │ ├── bottom_toolbar_widget.dart
│ │ │ │ ├── custom_slider_bar_shape_widget.dart
│ │ │ │ ├── gesture_area_widget.dart
│ │ │ │ ├── my_video_screen.dart
│ │ │ │ ├── rapple_painter.dart
│ │ │ │ └── top_toolbar_widget.dart
│ │ │ │ ├── private_or_deleted_video_widget.dart
│ │ │ │ ├── video_detail_info_skeleton_widget.dart
│ │ │ │ ├── video_rating_animation.dart
│ │ │ │ └── volume_control_widget.dart
│ │ └── widgets
│ │ │ ├── MDToastWidget.dart
│ │ │ ├── add_to_favorite_dialog.dart
│ │ │ ├── ai_translation_toggle_button.dart
│ │ │ ├── avatar_widget.dart
│ │ │ ├── base
│ │ │ └── base_input_dialog.dart
│ │ │ ├── base_card_list_item_widget.dart
│ │ │ ├── common_header.dart
│ │ │ ├── common_list_view_helper.dart
│ │ │ ├── custom_markdown_body_widget.dart
│ │ │ ├── empty_widget.dart
│ │ │ ├── error_widget.dart
│ │ │ ├── follow_button_widget.dart
│ │ │ ├── friend_button_widget.dart
│ │ │ ├── global_drawer_content_widget.dart
│ │ │ ├── glow_notification_widget.dart
│ │ │ ├── google_search_panel_widget.dart
│ │ │ ├── lazy_indexed_stack.dart
│ │ │ ├── like_button_widget.dart
│ │ │ ├── link_input_dialog_widget.dart
│ │ │ ├── loading_button_widget.dart
│ │ │ ├── markdown_syntax_help_dialog.dart
│ │ │ ├── markdown_translation_controller.dart
│ │ │ ├── my_loading_more_indicator_widget.dart
│ │ │ ├── privacy_over_lay_widget.dart
│ │ │ ├── shimmer_card.dart
│ │ │ ├── shimmer_loading_widget.dart
│ │ │ ├── top_padding_height_widget.dart
│ │ │ ├── translation_dialog_widget.dart
│ │ │ ├── translation_language_selector.dart
│ │ │ ├── translation_powered_by_widget.dart
│ │ │ ├── user_card.dart
│ │ │ ├── user_name_widget.dart
│ │ │ └── window_layout_widget.dart
│ └── utils
│ │ ├── exit_confirm_util.dart
│ │ ├── markdown_formatter.dart
│ │ ├── media_layout_utils.dart
│ │ └── url_utils.dart
├── common
│ ├── constants.dart
│ └── enums
│ │ └── media_enums.dart
├── db
│ ├── database_service.dart
│ ├── migration_manager.dart
│ ├── migrations
│ │ ├── migration.dart
│ │ ├── migration_v1.dart
│ │ ├── migration_v2.dart
│ │ ├── migration_v3.dart
│ │ ├── migration_v4.dart
│ │ ├── migration_v5.dart
│ │ ├── migration_v6_config.dart
│ │ ├── migration_v7_config_storage.dart
│ │ └── migration_v8_disable_theater.dart
│ └── sqlite3
│ │ ├── native.dart
│ │ ├── sqlite3.dart
│ │ ├── unsupported.dart
│ │ └── web.dart
├── i18n
│ ├── en.i18n.yaml
│ ├── ja.i18n.yaml
│ ├── strings.g.dart
│ ├── strings_en.g.dart
│ ├── strings_ja.g.dart
│ ├── strings_zh_CN.g.dart
│ ├── strings_zh_TW.g.dart
│ ├── zh-CN.i18n.yaml
│ └── zh-TW.i18n.yaml
├── main.dart
└── utils
│ ├── common_utils.dart
│ ├── easy_throttle.dart
│ ├── image_utils.dart
│ ├── logger_utils.dart
│ ├── platforms
│ └── microsoft_windows_registry_utils.dart
│ ├── proxy
│ ├── proxy_util.dart
│ ├── proxy_util_io.dart
│ ├── proxy_util_stub.dart
│ ├── proxy_util_web.dart
│ └── system_proxy_settings.dart
│ ├── vibrate_utils.dart
│ ├── widget_extensions.dart
│ └── x_version_calculator_utils.dart
├── linux
├── .gitignore
├── CMakeLists.txt
├── flutter
│ ├── CMakeLists.txt
│ ├── generated_plugin_registrant.cc
│ ├── generated_plugin_registrant.h
│ └── generated_plugins.cmake
├── main.cc
├── my_application.cc
└── my_application.h
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Podfile
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── app_icon_1024.png
│ │ │ ├── app_icon_128.png
│ │ │ ├── app_icon_16.png
│ │ │ ├── app_icon_256.png
│ │ │ ├── app_icon_32.png
│ │ │ ├── app_icon_512.png
│ │ │ └── app_icon_64.png
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── Configs
│ │ ├── AppInfo.xcconfig
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
└── RunnerTests
│ └── RunnerTests.swift
├── pubspec.lock
├── pubspec.yaml
├── slang.yaml
├── update_logs.yaml
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
├── manifest.json
└── sqlite3.wasm
└── windows
├── .gitignore
├── CMakeLists.txt
├── flutter
├── CMakeLists.txt
├── generated_plugin_registrant.cc
├── generated_plugin_registrant.h
└── generated_plugins.cmake
└── runner
├── CMakeLists.txt
├── Runner.rc
├── flutter_window.cpp
├── flutter_window.h
├── main.cpp
├── resource.h
├── resources
└── app_icon.ico
├── runner.exe.manifest
├── utils.cpp
├── utils.h
├── win32_window.cpp
└── win32_window.h
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug Report / 问题报告
3 | about: Create a report to help us improve / 创建报告以帮助我们改进
4 | title: '[Bug] '
5 | labels: 'bug | 问题'
6 | assignees: ''
7 | ---
8 |
9 | ### Bug Description / 问题描述
10 |
11 |
12 |
13 | ### Steps To Reproduce / 复现步骤
14 | 1.
15 | 2.
16 | 3.
17 |
18 | ### Expected Behavior / 预期行为
19 |
20 |
21 |
22 | ### Actual Behavior / 实际行为
23 |
24 |
25 |
26 | ### Environment / 环境信息
27 | - OS / 操作系统: [e.g. Windows 10, macOS]
28 | - Browser / 浏览器: [e.g. Chrome, Safari]
29 | - Version / 版本: [e.g. 22]
30 |
31 | ### Additional Context / 其他信息
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature Request & Improvement / 功能请求和优化建议
3 | about: Suggest a new feature or improvement for this project / 为项目提出新功能或改进建议
4 | title: '[Feature] '
5 | labels: 'enhancement | 功能增强'
6 | assignees: ''
7 | ---
8 |
9 | ### Type / 类型
10 |
11 | - [ ] New Feature Request / 新功能请求
12 | - [ ] Improvement for Existing Feature / 现有功能优化
13 |
14 | ### Description / 描述
15 |
16 |
17 |
18 | ### Use Case / 使用场景
19 |
20 |
21 |
22 | ### Current Solution / 当前解决方案
23 |
24 |
25 |
26 | ### Proposed Solution / 期望的解决方案
27 |
28 |
29 |
30 | ### Alternative Solutions / 替代方案
31 |
32 |
33 |
34 | ### Additional Context / 其他信息
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .build/
9 | .buildlog/
10 | .history
11 | .svn/
12 | .swiftpm/
13 | migrate_working_dir/
14 |
15 | # IntelliJ related
16 | *.iml
17 | *.ipr
18 | *.iws
19 | .idea/
20 |
21 | # The .vscode folder contains launch configuration and tasks you configure in
22 | # VS Code which you may wish to be included in version control, so this line
23 | # is commented out by default.
24 | #.vscode/
25 |
26 | # Flutter/Dart/Pub related
27 | **/doc/api/
28 | **/ios/Flutter/.last_build_id
29 | .dart_tool/
30 | .flutter-plugins
31 | .flutter-plugins-dependencies
32 | .pub-cache/
33 | .pub/
34 | /build/
35 |
36 | # Symbolication related
37 | app.*.symbols
38 |
39 | # Obfuscation related
40 | app.*.map.json
41 |
42 | # Android Studio will place build artifacts here
43 | /android/app/debug
44 | /android/app/profile
45 | /android/app/release
46 | # build
47 | build/
48 |
--------------------------------------------------------------------------------
/.vscode/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # 检查命令行参数
4 | platform=$1
5 |
6 | case $platform in
7 | "android")
8 | flutter build apk --release
9 | ;;
10 | "windows")
11 | flutter build windows --release
12 | ;;
13 | "macos")
14 | flutter build macos --release
15 | ;;
16 | "linux")
17 | flutter build linux --release
18 | ;;
19 | "web")
20 | flutter build web --release
21 | ;;
22 | "all")
23 | flutter build windows --release
24 | flutter build macos --release
25 | flutter build linux --release
26 | flutter build web --release
27 | flutter build apk --release
28 | ;;
29 | *)
30 | echo "Usage: ./build.sh [windows|macos|linux|web|all]"
31 | exit 1
32 | ;;
33 | esac
34 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 i_iwara
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This file configures the analyzer, which statically analyzes Dart code to
2 | # check for errors, warnings, and lints.
3 | #
4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
6 | # invoked from the command line by running `flutter analyze`.
7 |
8 | # The following line activates a set of recommended lints for Flutter apps,
9 | # packages, and plugins designed to encourage good coding practices.
10 | include: package:flutter_lints/flutter.yaml
11 | analyzer:
12 | enable-experiment:
13 | - macros
14 | linter:
15 | # The lint rules applied to this project can be customized in the
16 | # section below to disable rules from the `package:flutter_lints/flutter.yaml`
17 | # included above or to enable additional rules. A list of all available lints
18 | # and their documentation is published at https://dart.dev/lints.
19 | #
20 | # Instead of disabling a lint rule for the entire project in the
21 | # section below, it can also be suppressed for a single line of code
22 | # or a specific dart file by using the `// ignore: name_of_lint` and
23 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file
24 | # producing the lint.
25 | rules:
26 | # avoid_print: false # Uncomment to disable the `avoid_print` rule
27 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
28 |
29 | # Additional information about this file can be found at
30 | # https://dart.dev/guides/language/analysis-options
31 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/to/reference-keystore
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id "com.android.application"
3 | id "kotlin-android"
4 | id "dev.flutter.flutter-gradle-plugin"
5 | }
6 |
7 | android {
8 | namespace = "m.c.g.a.i_iwara"
9 | compileSdk = flutter.compileSdkVersion
10 | ndkVersion "27.0.12077973"
11 |
12 | compileOptions {
13 | sourceCompatibility = JavaVersion.VERSION_21
14 | targetCompatibility = JavaVersion.VERSION_21
15 | }
16 |
17 | kotlinOptions {
18 | jvmTarget = JavaVersion.VERSION_21
19 | }
20 |
21 | defaultConfig {
22 | applicationId = "m.c.g.a.i_iwara"
23 | minSdk = 24
24 | targetSdk = flutter.targetSdkVersion
25 | versionCode = flutter.versionCode
26 | versionName = flutter.versionName
27 | }
28 |
29 | // 配置正式签名(正式构建时使用)
30 | signingConfigs {
31 | release {
32 | // 这里的路径应该与 GitHub Action 解码后存放的路径一致
33 | storeFile file("keystore.jks")
34 | storePassword System.getenv("KEYSTORE_PASSWORD") ?: project.findProperty("MY_KEYSTORE_PASSWORD")
35 | keyAlias System.getenv("KEY_ALIAS") ?: project.findProperty("MY_KEY_ALIAS")
36 | keyPassword System.getenv("KEY_PASSWORD") ?: project.findProperty("MY_KEY_PASSWORD")
37 | }
38 | }
39 |
40 | buildTypes {
41 | release {
42 | // 正式构建时启用正式签名
43 | signingConfig signingConfigs.release
44 | minifyEnabled false
45 | shrinkResources false
46 | }
47 | debug {
48 | signingConfig signingConfigs.debug
49 | }
50 | }
51 |
52 | splits {
53 | abi {
54 | enable true
55 | reset()
56 | include 'arm64-v8a', 'armeabi-v7a', 'x86_64'
57 | universalApk true
58 | }
59 | }
60 |
61 | packagingOptions {
62 | jniLibs {
63 | useLegacyPackaging = true
64 | }
65 | }
66 | }
67 |
68 | dependencies {
69 | implementation 'com.google.errorprone:error_prone_annotations:2.10.0'
70 | implementation 'com.google.code.findbugs:jsr305:3.0.2'
71 | }
72 |
73 | flutter {
74 | source = "../.."
75 | }
76 |
--------------------------------------------------------------------------------
/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # 已有的规则
2 | -keep class com.google.errorprone.annotations.** { *; }
3 | -keep class javax.annotation.** { *; }
4 | -dontwarn com.google.errorprone.annotations.**
5 | -dontwarn javax.annotation.**
6 |
7 | # 添加 media_kit 相关规则
8 | -keep class com.arthenica.ffmpegkit.** { *; }
9 | -keep class com.google.crypto.tink.** { *; }
10 | -dontwarn com.google.crypto.tink.**
11 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/launcher_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-hdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-mdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffff
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | }
6 | }
7 |
8 | rootProject.buildDir = "../build"
9 |
10 | subprojects {
11 | project.buildDir = "${rootProject.buildDir}/${project.name}"
12 | project.evaluationDependsOn(":app")
13 | }
14 |
15 | tasks.register("clean", Delete) {
16 | delete rootProject.buildDir
17 | }
18 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 | # ????????? JDK ???????????????? JDK
5 | MY_KEYSTORE_PASSWORD=${KEYSTORE_PASSWORD}
6 | MY_KEY_ALIAS=${KEY_ALIAS}
7 | MY_KEY_PASSWORD=${KEY_PASSWORD}
8 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | def flutterSdkPath = {
3 | def properties = new Properties()
4 | file("local.properties").withInputStream { properties.load(it) }
5 | def flutterSdkPath = properties.getProperty("flutter.sdk")
6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
7 | return flutterSdkPath
8 | }()
9 |
10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
11 |
12 | repositories {
13 | google()
14 | mavenCentral()
15 | gradlePluginPortal()
16 | }
17 | }
18 |
19 | plugins {
20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0"
21 | id "com.android.application" version "8.7.3" apply false
22 | id "org.jetbrains.kotlin.android" version "2.0.21" apply false
23 | }
24 |
25 | include ":app"
26 |
--------------------------------------------------------------------------------
/assets/icon/launcher_icon_v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/assets/icon/launcher_icon_v2.png
--------------------------------------------------------------------------------
/assets/images/2.0x/flutter_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/assets/images/2.0x/flutter_logo.png
--------------------------------------------------------------------------------
/assets/images/3.0x/flutter_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/assets/images/3.0x/flutter_logo.png
--------------------------------------------------------------------------------
/assets/images/flutter_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/assets/images/flutter_logo.png
--------------------------------------------------------------------------------
/assets/svg/app_enter_fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/svg/app_exit_fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/imgs/all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/all.png
--------------------------------------------------------------------------------
/docs/imgs/dingyue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/dingyue.png
--------------------------------------------------------------------------------
/docs/imgs/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/download.png
--------------------------------------------------------------------------------
/docs/imgs/filter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/filter.png
--------------------------------------------------------------------------------
/docs/imgs/gonggao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/gonggao.png
--------------------------------------------------------------------------------
/docs/imgs/huihua.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/huihua.png
--------------------------------------------------------------------------------
/docs/imgs/localshoucang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/localshoucang.png
--------------------------------------------------------------------------------
/docs/imgs/luntan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/luntan.png
--------------------------------------------------------------------------------
/docs/imgs/luntanxaingqing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/luntanxaingqing.png
--------------------------------------------------------------------------------
/docs/imgs/pinglun.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/pinglun.png
--------------------------------------------------------------------------------
/docs/imgs/record.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/record.png
--------------------------------------------------------------------------------
/docs/imgs/shezhi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/shezhi.png
--------------------------------------------------------------------------------
/docs/imgs/shipin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/shipin.png
--------------------------------------------------------------------------------
/docs/imgs/shipin2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/shipin2.png
--------------------------------------------------------------------------------
/docs/imgs/shipinliebiao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/shipinliebiao.png
--------------------------------------------------------------------------------
/docs/imgs/sousuo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/sousuo.png
--------------------------------------------------------------------------------
/docs/imgs/tongzhi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/tongzhi.png
--------------------------------------------------------------------------------
/docs/imgs/tuku.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/tuku.png
--------------------------------------------------------------------------------
/docs/imgs/tukuliebiao.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/tukuliebiao.png
--------------------------------------------------------------------------------
/docs/imgs/zuozhe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/docs/imgs/zuozhe.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 12.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/ios/Podfile:
--------------------------------------------------------------------------------
1 | # Uncomment this line to define a global platform for your project
2 | # platform :ios, '12.0'
3 |
4 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
5 | ENV['COCOAPODS_DISABLE_STATS'] = 'true'
6 |
7 | project 'Runner', {
8 | 'Debug' => :debug,
9 | 'Profile' => :release,
10 | 'Release' => :release,
11 | }
12 |
13 | def flutter_root
14 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
15 | unless File.exist?(generated_xcode_build_settings_path)
16 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
17 | end
18 |
19 | File.foreach(generated_xcode_build_settings_path) do |line|
20 | matches = line.match(/FLUTTER_ROOT\=(.*)/)
21 | return matches[1].strip if matches
22 | end
23 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
24 | end
25 |
26 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
27 |
28 | flutter_ios_podfile_setup
29 |
30 | target 'Runner' do
31 | use_frameworks!
32 | use_modular_headers!
33 |
34 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
35 | target 'RunnerTests' do
36 | inherit! :search_paths
37 | end
38 | end
39 |
40 | post_install do |installer|
41 | installer.pods_project.targets.each do |target|
42 | flutter_additional_ios_build_settings(target)
43 | end
44 | end
45 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {"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":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"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":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@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"}}
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FoxSensei001/LoveIwara/60a821aa324ce506080136ffb85b171b8ae08b17/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/ios/RunnerTests/RunnerTests.swift:
--------------------------------------------------------------------------------
1 | import Flutter
2 | import UIKit
3 | import XCTest
4 |
5 | class RunnerTests: XCTestCase {
6 |
7 | func testExample() {
8 | // If you add code to the Runner application, consider adding tests here.
9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest.
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/lib/app/models/api_result.model.dart:
--------------------------------------------------------------------------------
1 | import 'package:i_iwara/i18n/strings.g.dart' as slang;
2 |
3 | /// Result
4 | class ApiResult {
5 | final String message;
6 | final int code;
7 | final T? data;
8 |
9 | bool get isSuccess => code == 200; // 改为通过状态码判断成功
10 | bool get isFail => !isSuccess;
11 |
12 | // 私有化构造函数
13 | ApiResult._(this.message, this.data, this.code);
14 |
15 | // 成功
16 | factory ApiResult.success({
17 | String? message,
18 | T? data,
19 | int code = 200,
20 | String? custMessage
21 | }) {
22 | return ApiResult._(custMessage ?? message ?? slang.t.common.success, data, code);
23 | }
24 |
25 | // 失败
26 | factory ApiResult.fail(String message, {T? data, int code = 500}) {
27 | return ApiResult._(message, data, code);
28 | }
29 |
30 | @override
31 | String toString() {
32 | return 'ApiResult{message: $message, code: $code, data: $data, isSuccess: $isSuccess}';
33 | }
34 | }
35 |
36 | // 测试结果模型
37 | class AITestResult {
38 | final String? rawResponse;
39 | final String? translatedText;
40 | final bool connectionValid;
41 | final String custMessage;
42 |
43 | AITestResult({
44 | this.rawResponse,
45 | this.translatedText,
46 | this.connectionValid = false,
47 | required this.custMessage
48 | });
49 |
50 | @override
51 | String toString() {
52 | return 'AITestResult{connectionValid: $connectionValid, custMessage: $custMessage, rawResponse: $rawResponse, translatedText: $translatedText}';
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/lib/app/models/captcha.model.dart:
--------------------------------------------------------------------------------
1 | // models/captcha.model.dart
2 | class Captcha {
3 | final String id;
4 | final String data; // Base64 image data URI
5 |
6 | Captcha({required this.id, required this.data});
7 |
8 | factory Captcha.fromJson(Map json) {
9 | return Captcha(
10 | id: json['id'],
11 | data: json['data'],
12 | );
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/lib/app/models/custom_thumbnail.model.dart:
--------------------------------------------------------------------------------
1 | class CustomThumbnail {
2 | final String id;
3 | final String type;
4 | final String path;
5 | final String name;
6 | final String mime;
7 | final int? size;
8 | final int? width;
9 | final int? height;
10 | final DateTime? createdAt;
11 | final DateTime? updatedAt;
12 |
13 | CustomThumbnail({
14 | required this.id,
15 | required this.type,
16 | required this.path,
17 | required this.name,
18 | required this.mime,
19 | this.size,
20 | this.width,
21 | this.height,
22 | this.createdAt,
23 | this.updatedAt,
24 | });
25 |
26 | factory CustomThumbnail.fromJson(Map json) {
27 | return CustomThumbnail(
28 | id: json['id'],
29 | type: json['type'],
30 | path: json['path'],
31 | name: json['name'],
32 | mime: json['mime'],
33 | size: json['size'] ?? 0,
34 | width: json['width'] ?? 0,
35 | height: json['height'] ?? 0,
36 | createdAt: json['createdAt'] == null ? null : DateTime.parse(json['createdAt']),
37 | updatedAt: json['updatedAt'] == null ? null : DateTime.parse(json['updatedAt']),
38 | );
39 | }
40 |
41 | Map toJson() {
42 | return {
43 | 'id': id,
44 | 'type': type,
45 | 'path': path,
46 | 'name': name,
47 | 'mime': mime,
48 | 'size': size,
49 | 'width': width,
50 | 'height': height,
51 | 'createdAt': createdAt?.toIso8601String(),
52 | 'updatedAt': updatedAt?.toIso8601String(),
53 | };
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/lib/app/models/dto/escape_intent.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class EscapeIntent extends Intent {
4 | const EscapeIntent();
5 | }
6 |
--------------------------------------------------------------------------------
/lib/app/models/dto/forum_thread_section_dto.dart:
--------------------------------------------------------------------------------
1 | /// 论坛帖子分类的DTO
2 | class ForumThreadSectionDto {
3 | final String id; // 分类id
4 | String name; // 分类名称
5 | String description; // 分类描述
6 | String group; // 组
7 | bool locked; // 是否锁定
8 | int numPosts; // 帖子数
9 | int numThreads; // 主题数
10 |
11 | ForumThreadSectionDto({
12 | required this.id,
13 | this.name = '',
14 | this.description = '',
15 | this.group = '',
16 | this.locked = false,
17 | this.numPosts = 0,
18 | this.numThreads = 0,
19 | });
20 |
21 | factory ForumThreadSectionDto.fromJson(Map json) {
22 | return ForumThreadSectionDto(
23 | id: json['id'],
24 | name: json['name'] ?? '',
25 | description: json['description'] ?? '',
26 | group: json['group'] ?? '',
27 | locked: json['locked'] ?? false,
28 | numPosts: json['numPosts'] ?? 0,
29 | numThreads: json['numThreads'] ?? 0,
30 | );
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/lib/app/models/dto/profile_user_dto.dart:
--------------------------------------------------------------------------------
1 | import 'package:i_iwara/app/models/tag.model.dart';
2 | import 'package:i_iwara/app/models/user.model.dart';
3 |
4 | class ProfileUserDto {
5 | final User? user;
6 | final Profile? profile;
7 | final List? tagBlacklist;
8 | final Notifications? notifications;
9 | final int? balance;
10 |
11 | ProfileUserDto({
12 | this.user,
13 | this.profile,
14 | this.tagBlacklist,
15 | this.notifications,
16 | this.balance,
17 | });
18 |
19 | factory ProfileUserDto.fromJson(Map json) {
20 | return ProfileUserDto(
21 | user: json['user'] != null ? User.fromJson(json['user']) : null,
22 | profile: json['profile'] != null ? Profile.fromJson(json['profile']) : null,
23 | tagBlacklist: json['tagBlacklist'] != null
24 | ? (json['tagBlacklist'] as List).map((i) => Tag.fromJson(i)).toList()
25 | : null,
26 | notifications: json['notifications'] != null
27 | ? Notifications.fromJson(json['notifications'])
28 | : null,
29 | balance: json['balance'],
30 | );
31 | }
32 | }
33 |
34 | class Profile {
35 | final String? body;
36 | final String? header;
37 | final DateTime? createdAt;
38 | final DateTime? updatedAt;
39 |
40 | Profile({
41 | this.body,
42 | this.header,
43 | this.createdAt,
44 | this.updatedAt,
45 | });
46 |
47 | factory Profile.fromJson(Map json) {
48 | return Profile(
49 | body: json['body'],
50 | header: json['header'],
51 | createdAt: json['createdAt'] != null
52 | ? DateTime.parse(json['createdAt'])
53 | : null,
54 | updatedAt: json['updatedAt'] != null
55 | ? DateTime.parse(json['updatedAt'])
56 | : null,
57 | );
58 | }
59 | }
60 |
61 | class Notifications {
62 | final bool? mention;
63 | final bool? reply;
64 | final bool? comment;
65 |
66 | Notifications({
67 | this.mention,
68 | this.reply,
69 | this.comment,
70 | });
71 |
72 | factory Notifications.fromJson(Map json) {
73 | return Notifications(
74 | mention: json['mention'],
75 | reply: json['reply'],
76 | comment: json['comment'],
77 | );
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/lib/app/models/dto/user_dto.dart:
--------------------------------------------------------------------------------
1 | class UserDTO {
2 | final String id;
3 | final String name;
4 | final String username;
5 | final String avatarUrl;
6 | DateTime? likedTime;
7 |
8 | UserDTO({
9 | required this.id,
10 | required this.name,
11 | required this.username,
12 | required this.avatarUrl,
13 | this.likedTime,
14 | });
15 |
16 | factory UserDTO.fromJson(Map json) {
17 | return UserDTO(
18 | id: json['id'],
19 | name: json['name'] ?? '',
20 | username: json['username'] ?? '',
21 | avatarUrl: json['avatarUrl'] ?? '',
22 | likedTime: json['likedTime'] != null ? DateTime.parse(json['likedTime']) : null,
23 | );
24 | }
25 |
26 | Map toJson() {
27 | return {
28 | 'id': id,
29 | 'name': name,
30 | 'username': username,
31 | 'avatarUrl': avatarUrl,
32 | 'likedTime': likedTime?.toIso8601String(),
33 | };
34 | }
35 |
36 | UserDTO copyWith({
37 | String? name,
38 | String? username,
39 | String? avatarUrl,
40 | DateTime? likedTime,
41 | }) {
42 | return UserDTO(
43 | id: id,
44 | name: name ?? this.name,
45 | username: username ?? this.username,
46 | avatarUrl: avatarUrl ?? this.avatarUrl,
47 | likedTime: likedTime ?? this.likedTime,
48 | );
49 | }
50 | }
--------------------------------------------------------------------------------
/lib/app/models/dto/user_request_dto.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:i_iwara/app/models/user.model.dart';
3 |
4 | /// 应用在 朋友请求列表
5 | /// target:如果target是自己,那么表示user是别人,别人请求加我
6 | /// target:如果target不是自己,那么表示user是我,我请求加别人
7 | class UserRequestDTO {
8 | final String id;
9 | final DateTime createdAt;
10 | final User target; // 目标用户,
11 | final User user; // 请求用户
12 |
13 | UserRequestDTO({
14 | required this.id,
15 | required this.createdAt,
16 | required this.target,
17 | required this.user,
18 | });
19 |
20 | factory UserRequestDTO.fromJson(Map json) {
21 | return UserRequestDTO(
22 | id: json['id'],
23 | createdAt: DateTime.parse(json['createdAt']),
24 | target: User.fromJson(json['target']),
25 | user: User.fromJson(json['user']),
26 | );
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/lib/app/models/favorite/favorite_folder.model.dart:
--------------------------------------------------------------------------------
1 | import 'package:uuid/uuid.dart';
2 |
3 | class FavoriteFolder {
4 | final String id;
5 | final String title;
6 | final String? description;
7 | final DateTime createdAt;
8 | final DateTime updatedAt;
9 | final int? itemCount; // 收藏项数量,可选
10 |
11 | FavoriteFolder({
12 | String? id,
13 | required this.title,
14 | this.description,
15 | DateTime? createdAt,
16 | DateTime? updatedAt,
17 | this.itemCount,
18 | }) : id = id ?? const Uuid().v4(),
19 | createdAt = createdAt ?? DateTime.now(),
20 | updatedAt = updatedAt ?? DateTime.now();
21 |
22 | factory FavoriteFolder.fromJson(Map json) {
23 | return FavoriteFolder(
24 | id: json['id'],
25 | title: json['title'],
26 | description: json['description'],
27 | createdAt: json['created_at'] != null
28 | ? DateTime.fromMillisecondsSinceEpoch(json['created_at'] * 1000)
29 | : null,
30 | updatedAt: json['updated_at'] != null
31 | ? DateTime.fromMillisecondsSinceEpoch(json['updated_at'] * 1000)
32 | : null,
33 | itemCount: json['item_count'],
34 | );
35 | }
36 |
37 | Map toJson() {
38 | return {
39 | 'id': id,
40 | 'title': title,
41 | 'description': description,
42 | 'created_at': createdAt.millisecondsSinceEpoch ~/ 1000,
43 | 'updated_at': updatedAt.millisecondsSinceEpoch ~/ 1000,
44 | 'item_count': itemCount,
45 | };
46 | }
47 |
48 | FavoriteFolder copyWith({
49 | String? id,
50 | String? title,
51 | String? description,
52 | DateTime? createdAt,
53 | DateTime? updatedAt,
54 | int? itemCount,
55 | }) {
56 | return FavoriteFolder(
57 | id: id ?? this.id,
58 | title: title ?? this.title,
59 | description: description ?? this.description,
60 | createdAt: createdAt ?? this.createdAt,
61 | updatedAt: updatedAt ?? this.updatedAt,
62 | itemCount: itemCount ?? this.itemCount,
63 | );
64 | }
65 | }
--------------------------------------------------------------------------------
/lib/app/models/light_play_list.model.dart:
--------------------------------------------------------------------------------
1 | class LightPlaylistModel {
2 | String id;
3 | String title;
4 | int numVideos;
5 | bool added;
6 |
7 | LightPlaylistModel({
8 | required this.id,
9 | required this.title,
10 | required this.numVideos,
11 | required this.added,
12 | });
13 |
14 | factory LightPlaylistModel.fromJson(Map json) {
15 | return LightPlaylistModel(
16 | id: json['id'],
17 | title: json['title'],
18 | numVideos: json['numVideos'],
19 | added: json['added'],
20 | );
21 | }
22 |
23 | Map toJson() {
24 | return {
25 | 'id': id,
26 | 'title': title,
27 | 'numVideos': numVideos,
28 | 'added': added,
29 | };
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/app/models/page_data.model.dart:
--------------------------------------------------------------------------------
1 | class PageData {
2 | final int count;
3 | final int page;
4 | final int limit;
5 | List results = [];
6 | Map? extras;
7 |
8 | PageData({
9 | required this.count,
10 | required this.page,
11 | required this.limit,
12 | required this.results,
13 | this.extras,
14 | });
15 |
16 | PageData.fromJson(Map data)
17 | : count = data['count'],
18 | page = data['page'],
19 | limit = data['limit'],
20 | results = [],
21 | extras = Map.from(data)
22 | ..removeWhere((key, value) =>
23 | ['count', 'page', 'limit', 'results'].contains(key));
24 |
25 | /// 工厂构造函数,用于处理泛型类型的转换
26 | static PageData fromJsonWithConverter(
27 | Map data,
28 | T Function(Map) fromJsonT,
29 | ) {
30 | return PageData(
31 | count: data['count'],
32 | page: data['page'],
33 | limit: data['limit'],
34 | results: (data['results'] as List)
35 | .map((item) => fromJsonT(item as Map))
36 | .toList(),
37 | extras: Map.from(data)
38 | ..removeWhere(
39 | (key, value) => ['count', 'page', 'limit', 'results'].contains(key)),
40 | );
41 | }
42 |
43 | @override
44 | String toString() {
45 | return 'PageData{count: $count, page: $page, limit: $limit, results: ${results.length} items${extras != null ? ", extras: $extras" : ""}}';
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/lib/app/models/play_list.model.dart:
--------------------------------------------------------------------------------
1 | import 'package:i_iwara/common/constants.dart';
2 |
3 | class PlaylistModel {
4 | String id;
5 | String title;
6 | int numVideos;
7 | String thumbnailUrl; // 封面图,截至2024-11-29,目前iwara并没有真正的为playlist设置封面图,如果后续iwara添加了,可以在这里添加
8 |
9 | PlaylistModel({
10 | required this.id,
11 | required this.title,
12 | required this.numVideos,
13 | required this.thumbnailUrl,
14 | });
15 |
16 | factory PlaylistModel.fromJson(Map json) {
17 | return PlaylistModel(
18 | id: json['id'],
19 | title: json['title'],
20 | numVideos: json['numVideos'],
21 | thumbnailUrl: json['thumbnailUrl'] ?? CommonConstants.defaultPlaylistThumbnailUrl,
22 | );
23 | }
24 |
25 | Map toJson() {
26 | return {
27 | 'id': id,
28 | 'title': title,
29 | 'numVideos': numVideos,
30 | 'thumbnailUrl': thumbnailUrl,
31 | };
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/lib/app/models/post.model.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:i_iwara/app/models/user.model.dart';
3 |
4 | class PostModel {
5 | final String id;
6 | final String title;
7 | final String body;
8 | final int? numViews;
9 | final DateTime createdAt;
10 | final DateTime updatedAt;
11 | final User user;
12 |
13 |
14 | PostModel({
15 | required this.id,
16 | required this.title,
17 | required this.body,
18 | required this.numViews,
19 | required this.createdAt,
20 | required this.updatedAt,
21 | required this.user,
22 | });
23 |
24 | factory PostModel.fromJson(Map json) {
25 | return PostModel(
26 | id: json['id'],
27 | title: json['title'],
28 | body: json['body'],
29 | numViews: json['numViews'],
30 | createdAt: DateTime.parse(json['createdAt']),
31 | updatedAt: DateTime.parse(json['updatedAt']),
32 | user: User.fromJson(json['user']),
33 | );
34 | }
35 |
36 | Map toJson() {
37 | return {
38 | 'id': id,
39 | 'title': title,
40 | 'body': body,
41 | 'numViews': numViews,
42 | 'createdAt': createdAt.toIso8601String(),
43 | 'updatedAt': updatedAt.toIso8601String(),
44 | 'user': user.toJson(),
45 | };
46 | }
47 |
48 | PostModel copyWith({
49 | String? id,
50 | String? title,
51 | String? body,
52 | int? numViews,
53 | DateTime? createdAt,
54 | DateTime? updatedAt,
55 | User? user,
56 | }) => PostModel(
57 | id: id ?? this.id,
58 | title: title ?? this.title,
59 | body: body ?? this.body,
60 | numViews: numViews ?? this.numViews,
61 | createdAt: createdAt ?? this.createdAt,
62 | updatedAt: updatedAt ?? this.updatedAt,
63 | user: user ?? this.user,
64 | );
65 | }
66 |
67 | class PostCooldownModel {
68 | final bool limited;
69 | final int remaining;
70 |
71 | PostCooldownModel({
72 | required this.limited,
73 | required this.remaining,
74 | });
75 |
76 | factory PostCooldownModel.fromJson(Map json) {
77 | return PostCooldownModel(
78 | limited: json['limited'],
79 | remaining: json['remaining'],
80 | );
81 | }
82 |
83 | Map toJson() {
84 | return {
85 | 'limited': limited,
86 | 'remaining': remaining,
87 | };
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/app/models/rules.model.dart:
--------------------------------------------------------------------------------
1 | import 'package:get/get.dart';
2 |
3 | class RulesModel {
4 | final String id;
5 | final int weight; // 权重 越小越靠前
6 | final Map title; // 标题 多语言
7 | final Map body; // 内容 使用markdown语法 {@link CustomMarkdownBody disableLinkClick: true}
8 | final String createdAt; // 创建时间
9 | final String updatedAt; // 更新时间
10 |
11 | RulesModel({
12 | required this.id,
13 | required this.weight,
14 | required this.title,
15 | required this.body,
16 | required this.createdAt,
17 | required this.updatedAt,
18 | });
19 |
20 | factory RulesModel.fromJson(Map json) {
21 | final Map titleMap = json['title'] as Map;
22 | final Map title = titleMap.map(
23 | (key, value) => MapEntry(key, value.toString()),
24 | );
25 |
26 | final Map bodyMap = json['body'] as Map;
27 | final Map body = bodyMap.map(
28 | (key, value) => MapEntry(key, value.toString()),
29 | );
30 |
31 | return RulesModel(
32 | id: json['id'],
33 | weight: json['weight'],
34 | title: title,
35 | body: body,
36 | createdAt: json['createdAt'],
37 | updatedAt: json['updatedAt'],
38 | );
39 | }
40 |
41 | String getLocalizedTitle() {
42 | final languageCode = Get.deviceLocale?.languageCode ?? 'en';
43 | // 如果当前语言存在对应的内容,则返回当前语言的内容
44 | if (title.containsKey(languageCode)) {
45 | return title[languageCode]!;
46 | }
47 | // 如果是中文但只有 zh,则返回 zh
48 | if (languageCode.startsWith('zh') && title.containsKey('zh')) {
49 | return title['zh']!;
50 | }
51 | // 如果都没有,返回英文内容,如果英文也没有,返回第一个可用的内容
52 | return title['en'] ?? title.values.first;
53 | }
54 |
55 | String getLocalizedBody() {
56 | final languageCode = Get.deviceLocale?.languageCode ?? 'en';
57 | // 如果当前语言存在对应的内容,则返回当前语言的内容
58 | if (body.containsKey(languageCode)) {
59 | return body[languageCode]!;
60 | }
61 | // 如果是中文但只有 zh,则返回 zh
62 | if (languageCode.startsWith('zh') && body.containsKey('zh')) {
63 | return body['zh']!;
64 | }
65 | // 如果都没有,返回英文内容,如果英文也没有,返回第一个可用的内容
66 | return body['en'] ?? body.values.first;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/lib/app/models/search_record.model.dart:
--------------------------------------------------------------------------------
1 | class SearchRecord {
2 | final String keyword;
3 | final DateTime lastUsedAt;
4 | int usedTimes;
5 |
6 | SearchRecord({
7 | required this.keyword,
8 | required this.lastUsedAt,
9 | this.usedTimes = 1,
10 | });
11 |
12 | Map toJson() => {
13 | 'keyword': keyword,
14 | 'lastUsedAt': lastUsedAt.toIso8601String(),
15 | 'usedTimes': usedTimes,
16 | };
17 |
18 | factory SearchRecord.fromJson(Map json) => SearchRecord(
19 | keyword: json['keyword'],
20 | lastUsedAt: DateTime.parse(json['lastUsedAt']),
21 | usedTimes: json['usedTimes'],
22 | );
23 | }
24 |
--------------------------------------------------------------------------------
/lib/app/models/sort.model.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:flutter/material.dart';
3 |
4 | import '../../common/constants.dart';
5 |
6 | class Sort {
7 | final SortId id;
8 | final String label;
9 | final String extData;
10 | final StatelessWidget? icon;
11 |
12 | const Sort({required this.id, required this.label, this.icon, this.extData = ''});
13 | }
--------------------------------------------------------------------------------
/lib/app/models/tag.model.dart:
--------------------------------------------------------------------------------
1 | class Tag {
2 | final String id;
3 | final String type;
4 | final bool sensitive;
5 |
6 | Tag(
7 | {required this.id,
8 | required this.type,
9 | this.sensitive = false});
10 |
11 | factory Tag.fromJson(Map json) {
12 | return Tag(
13 | id: json['id'],
14 | type: json['type'],
15 | sensitive: json['sensitive'] ?? false,
16 | );
17 | }
18 |
19 | Map toJson() {
20 | return {
21 | 'id': id,
22 | 'type': type,
23 | 'sensitive': sensitive,
24 | };
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/app/models/theme_mode.model.dart:
--------------------------------------------------------------------------------
1 | enum AppThemeMode {
2 | system, // 跟随系统
3 | light, // 亮色模式
4 | dark, // 暗色模式
5 | }
--------------------------------------------------------------------------------
/lib/app/models/update_info.model.dart:
--------------------------------------------------------------------------------
1 | class UpdateInfo {
2 | final String version; // 版本号
3 | final String date; // 更新日期
4 | final Map> changes; // 更新内容
5 | final String minVersion; // 最小版本号
6 |
7 | UpdateInfo({
8 | required this.version,
9 | required this.date,
10 | required this.changes,
11 | this.minVersion = '0.0.1',
12 | });
13 |
14 | factory UpdateInfo.fromYaml(Map yaml) {
15 | final changesMap = >{};
16 | final yamlChanges = yaml['changes'] as Map;
17 |
18 | yamlChanges.forEach((key, value) {
19 | changesMap[key.toString()] = List.from(value);
20 | });
21 |
22 | return UpdateInfo(
23 | version: yaml['version'] ?? '',
24 | date: yaml['date'] ?? '',
25 | changes: changesMap,
26 | minVersion: yaml['minVersion'] ?? '0.0.1',
27 | );
28 | }
29 |
30 | List getLocalizedChanges(String currentLocale) {
31 | return changes[currentLocale] ?? changes['en'] ?? changes['zh-CN'] ?? changes['zh-TW'] ?? changes['ja'] ?? [];
32 | }
33 | }
--------------------------------------------------------------------------------
/lib/app/models/user_avatar.model.dart:
--------------------------------------------------------------------------------
1 |
2 | import 'package:i_iwara/common/constants.dart';
3 |
4 | class UserAvatar {
5 | final String id;
6 | final String type;
7 | final String path;
8 | final String name;
9 | final String mime;
10 | final int? size;
11 | final int? width;
12 | final int? height;
13 | final DateTime createdAt;
14 | final DateTime updatedAt;
15 |
16 | UserAvatar({
17 | required this.id,
18 | required this.type,
19 | required this.path,
20 | required this.name,
21 | required this.mime,
22 | required this.size,
23 | this.width,
24 | this.height,
25 | required this.createdAt,
26 | required this.updatedAt,
27 | });
28 |
29 | factory UserAvatar.fromJson(Map json) {
30 | return UserAvatar(
31 | id: json['id'],
32 | type: json['type'],
33 | path: json['path'],
34 | name: json['name'],
35 | mime: json['mime'],
36 | size: json['size'],
37 | width: json['width'],
38 | height: json['height'],
39 | createdAt: json['createdAt'] == null ? DateTime.now() : DateTime.parse(json['createdAt']),
40 | updatedAt: json['updatedAt'] == null ? DateTime.now() : DateTime.parse(json['updatedAt']),
41 | );
42 | }
43 |
44 | Map toJson() {
45 | final data = {};
46 | data['id'] = id;
47 | data['type'] = type;
48 | data['path'] = path;
49 | data['name'] = name;
50 | data['mime'] = mime;
51 | data['size'] = size;
52 | data['width'] = width;
53 | data['height'] = height;
54 | data['createdAt'] = createdAt.toIso8601String();
55 | data['updatedAt'] = updatedAt.toIso8601String();
56 | return data;
57 | }
58 |
59 | String get avatarUrl {
60 | final isAnimated = mime == 'image/gif' || mime == 'image/webp' || mime == 'image/apng';
61 | if (isAnimated) {
62 | return CommonConstants.avatarOriginalUrl(id, name);
63 | }
64 | return CommonConstants.avatarUrl(id, name);
65 | }
66 | }
--------------------------------------------------------------------------------
/lib/app/models/user_notification_count.model.dart:
--------------------------------------------------------------------------------
1 |
2 | class UserNotificationCount {
3 | final int messages; // 消息
4 | final int notifications; // 通知
5 | final int friendRequests; // 好友请求
6 |
7 | UserNotificationCount({required this.messages, required this.notifications, required this.friendRequests});
8 |
9 | factory UserNotificationCount.fromJson(Map json) {
10 | return UserNotificationCount(
11 | messages: json['messages'],
12 | notifications: json['notifications'],
13 | friendRequests: json['friendRequests'],
14 | );
15 | }
16 |
17 | // toJson
18 | Map toJson() {
19 | return {
20 | 'messages': messages,
21 | 'notifications': notifications,
22 | 'friendRequests': friendRequests,
23 | };
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/app/models/video_source.model.dart:
--------------------------------------------------------------------------------
1 | // video_source.model.dart
2 |
3 | class VideoSource {
4 | final String id;
5 | final String? name; // 清晰度,例如 "360", "540", "720"
6 | final String? view;
7 | final String? download;
8 | final String? type; // 视频类型,例如 "video/mp4"
9 | final DateTime? createdAt;
10 | final DateTime? updatedAt;
11 | final VideoSrc? src;
12 |
13 | VideoSource({
14 | required this.id,
15 | this.name,
16 | this.view,
17 | this.download,
18 | this.type,
19 | this.createdAt,
20 | this.updatedAt,
21 | this.src,
22 | });
23 |
24 | factory VideoSource.fromJson(Map json) {
25 | return VideoSource(
26 | id: json['id'],
27 | name: json['name'],
28 | view: json['src'] != null ? 'https:${json['src']['view']}' : null,
29 | download:
30 | json['src'] != null ? 'https:${json['src']['download']}' : null,
31 | type: json['type'],
32 | createdAt:
33 | json['createdAt'] != null ? DateTime.parse(json['createdAt']) : null,
34 | updatedAt:
35 | json['updatedAt'] != null ? DateTime.parse(json['updatedAt']) : null,
36 | src: json['src'] != null ? VideoSrc.fromJson(json['src']) : null,
37 | );
38 | }
39 |
40 | Map toJson() {
41 | return {
42 | 'id': id,
43 | 'name': name,
44 | 'type': type,
45 | 'createdAt': createdAt?.toIso8601String(),
46 | 'updatedAt': updatedAt?.toIso8601String(),
47 | 'src': src?.toJson(),
48 | };
49 | }
50 | }
51 |
52 | class VideoSrc {
53 | final String? view;
54 | final String? download;
55 |
56 | VideoSrc({
57 | this.view, // 视频播放源
58 | this.download,
59 | });
60 |
61 | factory VideoSrc.fromJson(Map json) {
62 | return VideoSrc(
63 | view: json['view'], // 视频播放源
64 | download: json['download'],
65 | );
66 | }
67 |
68 | Map toJson() {
69 | return {
70 | 'view': view,
71 | 'download': download,
72 | };
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/lib/app/repositories/base_repository.dart:
--------------------------------------------------------------------------------
1 |
2 | import '../../db/database_service.dart';
3 |
4 | abstract class BaseRepository {
5 | final DatabaseService databaseService = DatabaseService();
6 |
7 | BaseRepository();
8 | }
--------------------------------------------------------------------------------
/lib/app/repositories/commons_repository.dart:
--------------------------------------------------------------------------------
1 | import 'package:i_iwara/utils/logger_utils.dart';
2 | import 'base_repository.dart';
3 |
4 | class CommonsRepository extends BaseRepository {
5 | CommonsRepository._privateConstructor();
6 | static final CommonsRepository instance = CommonsRepository._privateConstructor();
7 |
8 | // 获取配置
9 | Future getData(String key) async {
10 | try {
11 | final db = databaseService.database;
12 | final result = db.select(
13 | 'SELECT data FROM commons WHERE key = ?',
14 | [key],
15 | );
16 | if (result.isNotEmpty) {
17 | return result.first['data'] as String;
18 | }
19 | return null;
20 | } catch (e) {
21 | LogUtils.e('获取配置数据时出错', error: e);
22 | rethrow;
23 | }
24 | }
25 |
26 | // 保存配置
27 | Future setData(String key, String data) async {
28 | try {
29 | final db = databaseService.database;
30 | db.execute(
31 | '''
32 | INSERT INTO commons(key, data)
33 | VALUES(?, ?)
34 | ON CONFLICT(key) DO UPDATE SET
35 | data = excluded.data
36 | ''',
37 | [key, data],
38 | );
39 | } catch (e) {
40 | LogUtils.e('保存配置数据时出错', error: e);
41 | rethrow;
42 | }
43 | }
44 |
45 | // 删除配置
46 | Future deleteData(String key) async {
47 | try {
48 | final db = databaseService.database;
49 | db.execute(
50 | 'DELETE FROM commons WHERE key = ?',
51 | [key],
52 | );
53 | } catch (e) {
54 | LogUtils.e('删除配置数据时出错', error: e);
55 | rethrow;
56 | }
57 | }
58 |
59 | // 获取所有配置
60 | Future