├── app ├── .gitignore └── src │ ├── main │ ├── ic_launcher-playstore.png │ ├── res │ │ ├── drawable-v1 │ │ │ ├── c_fy.png │ │ │ ├── c_oned.png │ │ │ ├── c_onef.png │ │ │ ├── c_onem.png │ │ │ ├── c_oneo.png │ │ │ ├── c_oney.png │ │ │ ├── c_oy.png │ │ │ ├── c_teny.png │ │ │ ├── c_twod.png │ │ │ ├── c_twof.png │ │ │ ├── c_twom.png │ │ │ ├── c_twoo.png │ │ │ ├── c_twoy.png │ │ │ ├── c_ty.png │ │ │ ├── c_coolb.png │ │ │ ├── c_fived.png │ │ │ ├── c_fivef.png │ │ │ ├── c_fivem.png │ │ │ ├── c_fiveo.png │ │ │ ├── c_fivey.png │ │ │ ├── coolapk_emotion_68.png │ │ │ ├── coolapk_emotion_69.png │ │ │ ├── coolapk_emotion_70.png │ │ │ ├── coolapk_emotion_71.png │ │ │ ├── coolapk_emotion_72.png │ │ │ ├── coolapk_emotion_73.png │ │ │ ├── coolapk_emotion_74.png │ │ │ ├── coolapk_emotion_75.png │ │ │ ├── coolapk_emotion_76.png │ │ │ ├── coolapk_emotion_77.png │ │ │ ├── coolapk_emotion_78.png │ │ │ ├── coolapk_emotion_79.png │ │ │ ├── coolapk_emotion_80.png │ │ │ ├── coolapk_emotion_85.png │ │ │ ├── coolapk_emotion_86.png │ │ │ ├── coolapk_emotion_87.png │ │ │ ├── coolapk_emotion_88.png │ │ │ ├── coolapk_emotion_89.png │ │ │ ├── coolapk_emotion_90.png │ │ │ ├── coolapk_emotion_91.png │ │ │ ├── coolapk_emotion_92.png │ │ │ ├── coolapk_emotion_93.png │ │ │ ├── coolapk_emotion_94.png │ │ │ ├── coolapk_emotion_1010.png │ │ │ ├── coolapk_emotion_1011.png │ │ │ ├── coolapk_emotion_1012.png │ │ │ ├── coolapk_emotion_1013.png │ │ │ ├── coolapk_emotion_1014.png │ │ │ ├── coolapk_emotion_1015.png │ │ │ ├── coolapk_emotion_1016.png │ │ │ ├── coolapk_emotion_1017.png │ │ │ ├── coolapk_emotion_1018.png │ │ │ ├── coolapk_emotion_1019.png │ │ │ ├── coolapk_emotion_1020.png │ │ │ ├── coolapk_emotion_1021.png │ │ │ ├── coolapk_emotion_1024.png │ │ │ ├── coolapk_emotion_1025.png │ │ │ ├── coolapk_emotion_1026.png │ │ │ ├── coolapk_emotion_1027.png │ │ │ ├── coolapk_emotion_1028.png │ │ │ ├── coolapk_emotion_1029.png │ │ │ ├── coolapk_emotion_1030.png │ │ │ ├── coolapk_emotion_1031.png │ │ │ ├── coolapk_emotion_104.png │ │ │ ├── coolapk_emotion_105.png │ │ │ ├── coolapk_emotion_106.png │ │ │ ├── coolapk_emotion_107.png │ │ │ ├── coolapk_emotion_108.png │ │ │ ├── coolapk_emotion_109.png │ │ │ ├── coolapk_emotion_30_ok.png │ │ │ ├── coolapk_emotion_35_ye.png │ │ │ ├── coolapk_emotion_36_ku.png │ │ │ ├── coolapk_emotion_53_pu.png │ │ │ ├── coolapk_emotion_9_se.png │ │ │ ├── coolapk_emotion_103_nb.png │ │ │ ├── coolapk_emotion_12_wuyu.png │ │ │ ├── coolapk_emotion_15_fanu.png │ │ │ ├── coolapk_emotion_18_han.png │ │ │ ├── coolapk_emotion_23_shui.png │ │ │ ├── coolapk_emotion_28_ruo.png │ │ │ ├── coolapk_emotion_37_doge.png │ │ │ ├── coolapk_emotion_3_ciya.png │ │ │ ├── coolapk_emotion_44_pen.png │ │ │ ├── coolapk_emotion_59_erha.png │ │ │ ├── coolapk_emotion_5_keai.png │ │ │ ├── coolapk_emotion_60_kuan.png │ │ │ ├── coolapk_emotion_7_hehe.png │ │ │ ├── coolapk_emotion_100_qqdoge.png │ │ │ ├── coolapk_emotion_102_fadai.png │ │ │ ├── coolapk_emotion_10_aoman.png │ │ │ ├── coolapk_emotion_11_yiwen.png │ │ │ ├── coolapk_emotion_14_bishi.png │ │ │ ├── coolapk_emotion_16_tuosai.png │ │ │ ├── coolapk_emotion_17_tushe.png │ │ │ ├── coolapk_emotion_19_koubi.png │ │ │ ├── coolapk_emotion_1_hahaha.png │ │ │ ├── coolapk_emotion_20_qinqin.png │ │ │ ├── coolapk_emotion_21_penxue.png │ │ │ ├── coolapk_emotion_22_xiaoyan.png │ │ │ ├── coolapk_emotion_25_zaijian.png │ │ │ ├── coolapk_emotion_26_kelian.png │ │ │ ├── coolapk_emotion_27_qiang.png │ │ │ ├── coolapk_emotion_29_baoquan.png │ │ │ ├── coolapk_emotion_2_jingya.png │ │ │ ├── coolapk_emotion_31_xiaoku.png │ │ │ ├── coolapk_emotion_32_heiha.png │ │ │ ├── coolapk_emotion_33_wulian.png │ │ │ ├── coolapk_emotion_34_jizhi.png │ │ │ ├── coolapk_emotion_39_caidao.png │ │ │ ├── coolapk_emotion_40_aixin.png │ │ │ ├── coolapk_emotion_41_meigui.png │ │ │ ├── coolapk_emotion_42_diaoxie.png │ │ │ ├── coolapk_emotion_43_heixian.png │ │ │ ├── coolapk_emotion_45_yinxian.png │ │ │ ├── coolapk_emotion_46_nanguo.png │ │ │ ├── coolapk_emotion_47_weiqu.png │ │ │ ├── coolapk_emotion_49_huanhu.png │ │ │ ├── coolapk_emotion_4_liulei.png │ │ │ ├── coolapk_emotion_50_xinsui.png │ │ │ ├── coolapk_emotion_51_chigua.png │ │ │ ├── coolapk_emotion_52_hejiu.png │ │ │ ├── coolapk_emotion_61_lvmao.png │ │ │ ├── coolapk_emotion_62_huaji.png │ │ │ ├── coolapk_emotion_6_weixiao.png │ │ │ ├── coolapk_emotion_83_huoba.png │ │ │ ├── coolapk_emotion_84_baiyan.png │ │ │ ├── coolapk_emotion_8_piezui.png │ │ │ ├── coolapk_emotion_97_haixiu.png │ │ │ ├── coolapk_emotion_98_wunai.png │ │ │ ├── coolapk_emotion_99_zhoumei.png │ │ │ ├── coolapk_emotion_101_pyjiaoyi.png │ │ │ ├── coolapk_emotion_13_huaixiao.png │ │ │ ├── coolapk_emotion_24_wuzuixiao.png │ │ │ ├── coolapk_emotion_38_wozuimei.png │ │ │ ├── coolapk_emotion_55_lvyaowan.png │ │ │ ├── coolapk_emotion_57_dogehechi.png │ │ │ ├── coolapk_emotion_65_coshuaji.png │ │ │ ├── coolapk_emotion_81_naikezui.png │ │ │ ├── coolapk_emotion_82_miaomiao.png │ │ │ ├── coolapk_emotion_95_erhading.png │ │ │ ├── coolapk_emotion_96_kuanlvmao.png │ │ │ ├── coolapk_emotion_1022_zhenbuchuo.png │ │ │ ├── coolapk_emotion_1023_liewenhuke.png │ │ │ ├── coolapk_emotion_48_weiweiyixiao.png │ │ │ ├── coolapk_emotion_54_hongyaowan.png │ │ │ ├── coolapk_emotion_56_dogexiaoku.png │ │ │ ├── coolapk_emotion_63_liuhanhuaji.png │ │ │ ├── coolapk_emotion_64_shounuehuaji.png │ │ │ ├── coolapk_emotion_67_mojinghuaji.png │ │ │ ├── coolapk_emotion_66_doujiyanhuaji.png │ │ │ └── coolapk_emotion_58_dogeyuanliangta.png │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── values-night │ │ │ └── colors.xml │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.webp │ │ │ └── ic_launcher_round.webp │ │ ├── xml │ │ │ ├── file_provider_paths.xml │ │ │ ├── backup_rules.xml │ │ │ └── data_extraction_rules.xml │ │ ├── color │ │ │ └── image_stroke.xml │ │ ├── drawable │ │ │ ├── white_radius.xml │ │ │ ├── shape_oval_primary.xml │ │ │ ├── round_corners_12.xml │ │ │ ├── selector_emoji.xml │ │ │ ├── selector_emoji_indicator.xml │ │ │ ├── ic_photo.xml │ │ │ ├── outline_tag_24.xml │ │ │ ├── selector_bg_trans.xml │ │ │ ├── outline_image_24.xml │ │ │ ├── selector_emoji_indicator_selected.xml │ │ │ ├── selector_bg_12_trans.xml │ │ │ ├── outline_keyboard_hide_24.xml │ │ │ ├── outline_backspace_24.xml │ │ │ ├── selector_reply.xml │ │ │ ├── outline_alternate_email_24.xml │ │ │ ├── outline_keyboard_show_24.xml │ │ │ ├── outline_note_alt_24.xml │ │ │ ├── ic_launcher_foreground.xml │ │ │ ├── outline_emoji_emotions_24.xml │ │ │ ├── ic_subauthor.xml │ │ │ ├── ic_feed_top.xml │ │ │ └── ic_author.xml │ │ ├── values-v31 │ │ │ └── colors.xml │ │ ├── values-night-v31 │ │ │ └── colors.xml │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ ├── attrs.xml │ │ │ └── themes.xml │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── anim │ │ │ ├── indicator_animator.xml │ │ │ ├── anim_bottom_sheet_slide_down.xml │ │ │ ├── anim_bottom_sheet_slide_up.xml │ │ │ ├── indicator_animator_reverse.xml │ │ │ └── scale_with_alpha.xml │ │ └── layout │ │ │ ├── item_emoji.xml │ │ │ ├── dialog_refresh.xml │ │ │ ├── item_captcha.xml │ │ │ └── item_emoji_child_viewpager.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── c001apk │ │ │ └── compose │ │ │ ├── logic │ │ │ ├── state │ │ │ │ ├── State.kt │ │ │ │ ├── FooterState.kt │ │ │ │ └── LoadingState.kt │ │ │ ├── model │ │ │ │ ├── TopicBean.kt │ │ │ │ ├── AppItem.kt │ │ │ │ ├── OSSUploadPrepareModel.kt │ │ │ │ ├── PostReplyResponse.kt │ │ │ │ ├── HomeMenu.kt │ │ │ │ ├── DeviceInfo.kt │ │ │ │ ├── StringEntity.kt │ │ │ │ ├── LoginResponse.kt │ │ │ │ ├── UpdateCheckItem.kt │ │ │ │ ├── RecentAtUser.kt │ │ │ │ ├── LoadUrlResponse.kt │ │ │ │ ├── FeedContentResponse.kt │ │ │ │ ├── FeedArticleContentBean.kt │ │ │ │ ├── LikeResponse.kt │ │ │ │ ├── FeedEntity.kt │ │ │ │ ├── CheckCountResponse.kt │ │ │ │ ├── UpdateCheckResponse.kt │ │ │ │ ├── CreateFeedResponse.kt │ │ │ │ ├── OSSUploadPrepareResponse.kt │ │ │ │ ├── CheckResponse.kt │ │ │ │ ├── TotalReplyResponse.kt │ │ │ │ ├── MessageListResponse.kt │ │ │ │ ├── FeedAdapter.kt │ │ │ │ └── LikeAdapter.kt │ │ │ ├── providable │ │ │ │ └── LocalUserPreferences.kt │ │ │ ├── database │ │ │ │ ├── HomeMenuDatabase.kt │ │ │ │ ├── RecentAtUserDatabase.kt │ │ │ │ ├── StringEntityDatabase.kt │ │ │ │ └── HistoryFavoriteDatabase.kt │ │ │ ├── repository │ │ │ │ ├── HomeMenuRepo.kt │ │ │ │ ├── RecentAtUserRepo.kt │ │ │ │ ├── SearchHistoryRepo.kt │ │ │ │ ├── RecentEmojiRepo.kt │ │ │ │ └── BlackListRepo.kt │ │ │ ├── datastore │ │ │ │ └── UserPreferencesSerializer.kt │ │ │ └── dao │ │ │ │ ├── HistoryFavoriteDao.kt │ │ │ │ ├── HomeMenuDao.kt │ │ │ │ ├── RecentAtUserDao.kt │ │ │ │ └── StringEntityDao.kt │ │ │ ├── ui │ │ │ ├── theme │ │ │ │ ├── Color.kt │ │ │ │ └── Type.kt │ │ │ ├── component │ │ │ │ ├── Button.kt │ │ │ │ ├── FooterCard.kt │ │ │ │ ├── settings │ │ │ │ │ ├── SwitchListItem.kt │ │ │ │ │ ├── BasicListItem.kt │ │ │ │ │ ├── DropdownListItem.kt │ │ │ │ │ └── StateDropdownListItem.kt │ │ │ │ ├── cards │ │ │ │ │ ├── ChatTimeCard.kt │ │ │ │ │ ├── TextCard.kt │ │ │ │ │ ├── SearchHistoryCard.kt │ │ │ │ │ ├── TitleCard.kt │ │ │ │ │ └── IconMiniGridCard.kt │ │ │ │ ├── IconText.kt │ │ │ │ ├── NineImageView.kt │ │ │ │ └── CoilLoader.kt │ │ │ ├── webview │ │ │ │ └── WebViewViewModel.kt │ │ │ ├── home │ │ │ │ ├── topic │ │ │ │ │ └── HomeTopicViewModel.kt │ │ │ │ └── feed │ │ │ │ │ └── HomeFeedViewModel.kt │ │ │ ├── dyh │ │ │ │ ├── DyhContentViewModel.kt │ │ │ │ └── DyhContentScreen.kt │ │ │ ├── search │ │ │ │ ├── SearchViewModel.kt │ │ │ │ └── SearchContentViewModel.kt │ │ │ ├── coolpic │ │ │ │ ├── CoolPicContentViewModel.kt │ │ │ │ └── CoolPicContentScreen.kt │ │ │ ├── feed │ │ │ │ └── reply │ │ │ │ │ └── emoji │ │ │ │ │ ├── EmojiChildPagerAdapter.kt │ │ │ │ │ ├── EmojiPagerAdapter.kt │ │ │ │ │ └── EmojiGridAdapter.kt │ │ │ ├── topic │ │ │ │ ├── TopicContentViewModel.kt │ │ │ │ └── TopicContentScreen.kt │ │ │ ├── app │ │ │ │ ├── AppContentViewModel.kt │ │ │ │ └── AppContentScreen.kt │ │ │ ├── carousel │ │ │ │ └── CarouselContentScreen.kt │ │ │ ├── others │ │ │ │ └── CopyTextScreen.kt │ │ │ ├── history │ │ │ │ └── HistoryViewModel.kt │ │ │ └── base │ │ │ │ └── PrefsViewModel.kt │ │ │ ├── util │ │ │ ├── NetWorkUtil.kt │ │ │ ├── CookieUtil.kt │ │ │ ├── TokenDeviceUtils.kt │ │ │ └── AddCookiesInterceptor.kt │ │ │ ├── view │ │ │ ├── MyURLSpan.kt │ │ │ ├── CenteredImageSpan.kt │ │ │ ├── circleindicator │ │ │ │ └── Config.kt │ │ │ ├── BadgedImageView.kt │ │ │ └── CircleIndexIndicator.kt │ │ │ ├── di │ │ │ └── DataStoreModule.kt │ │ │ └── C001Application.kt │ └── proto │ │ └── UserPreferences.proto │ ├── test │ └── java │ │ └── com │ │ └── example │ │ └── c001apk │ │ └── compose │ │ └── ExampleUnitTest.kt │ └── androidTest │ └── java │ └── com │ └── example │ └── c001apk │ └── compose │ └── ExampleInstrumentedTest.kt ├── README.md ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── renovate.json ├── .gitignore ├── settings.gradle.kts └── gradle.properties /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /release 3 | /schemas -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # c001apk-compose 2 | 3 | test only 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/ic_launcher-playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/ic_launcher-playstore.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_oned.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_oned.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_onef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_onef.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_onem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_onem.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_oneo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_oneo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_oney.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_oney.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_oy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_oy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_teny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_teny.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_twod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_twod.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_twof.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_twof.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_twom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_twom.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_twoo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_twoo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_twoy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_twoy.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_ty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_ty.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_coolb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_coolb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fived.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fived.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fivef.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fivef.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fivem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fivem.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fiveo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fiveo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/c_fivey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/c_fivey.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #0DFFFFFF 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_68.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_69.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_69.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_70.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_71.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_72.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_73.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_74.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_75.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_76.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_77.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_78.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_79.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_79.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_80.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_85.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_85.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_86.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_86.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_87.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_88.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_89.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_89.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_90.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_91.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_91.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_92.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_92.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_93.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_93.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_94.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_94.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1010.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1010.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1011.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1012.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1012.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1013.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1013.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1014.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1014.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1015.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1016.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1016.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1017.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1018.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1019.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1019.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1020.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1020.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1021.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1021.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1024.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1025.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1026.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1026.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1027.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1027.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1028.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1028.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1029.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1029.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1030.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1030.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1031.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1031.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_104.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_105.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_106.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_107.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_108.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_109.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_30_ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_30_ok.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_35_ye.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_35_ye.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_36_ku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_36_ku.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_53_pu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_53_pu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_9_se.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_9_se.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_103_nb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_103_nb.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_12_wuyu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_12_wuyu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_15_fanu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_15_fanu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_18_han.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_18_han.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_23_shui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_23_shui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_28_ruo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_28_ruo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_37_doge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_37_doge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_3_ciya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_3_ciya.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_44_pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_44_pen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_59_erha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_59_erha.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_5_keai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_5_keai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_60_kuan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_60_kuan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_7_hehe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_7_hehe.png -------------------------------------------------------------------------------- /app/src/main/res/xml/file_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_100_qqdoge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_100_qqdoge.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_102_fadai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_102_fadai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_10_aoman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_10_aoman.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_11_yiwen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_11_yiwen.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_14_bishi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_14_bishi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_16_tuosai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_16_tuosai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_17_tushe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_17_tushe.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_19_koubi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_19_koubi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1_hahaha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1_hahaha.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_20_qinqin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_20_qinqin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_21_penxue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_21_penxue.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_22_xiaoyan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_22_xiaoyan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_25_zaijian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_25_zaijian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_26_kelian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_26_kelian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_27_qiang.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_27_qiang.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_29_baoquan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_29_baoquan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_2_jingya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_2_jingya.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_31_xiaoku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_31_xiaoku.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_32_heiha.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_32_heiha.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_33_wulian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_33_wulian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_34_jizhi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_34_jizhi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_39_caidao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_39_caidao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_40_aixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_40_aixin.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_41_meigui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_41_meigui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_42_diaoxie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_42_diaoxie.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_43_heixian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_43_heixian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_45_yinxian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_45_yinxian.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_46_nanguo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_46_nanguo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_47_weiqu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_47_weiqu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_49_huanhu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_49_huanhu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_4_liulei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_4_liulei.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_50_xinsui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_50_xinsui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_51_chigua.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_51_chigua.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_52_hejiu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_52_hejiu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_61_lvmao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_61_lvmao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_62_huaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_62_huaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_6_weixiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_6_weixiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_83_huoba.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_83_huoba.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_84_baiyan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_84_baiyan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_8_piezui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_8_piezui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_97_haixiu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_97_haixiu.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_98_wunai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_98_wunai.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_99_zhoumei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_99_zhoumei.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_101_pyjiaoyi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_101_pyjiaoyi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_13_huaixiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_13_huaixiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_24_wuzuixiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_24_wuzuixiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_38_wozuimei.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_38_wozuimei.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_55_lvyaowan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_55_lvyaowan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_57_dogehechi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_57_dogehechi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_65_coshuaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_65_coshuaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_81_naikezui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_81_naikezui.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_82_miaomiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_82_miaomiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_95_erhading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_95_erhading.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_96_kuanlvmao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_96_kuanlvmao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1022_zhenbuchuo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1022_zhenbuchuo.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_1023_liewenhuke.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_1023_liewenhuke.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_48_weiweiyixiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_48_weiweiyixiao.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_54_hongyaowan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_54_hongyaowan.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_56_dogexiaoku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_56_dogexiaoku.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_63_liuhanhuaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_63_liuhanhuaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_64_shounuehuaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_64_shounuehuaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_67_mojinghuaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_67_mojinghuaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_66_doujiyanhuaji.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_66_doujiyanhuaji.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v1/coolapk_emotion_58_dogeyuanliangta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bggRGjQaUbCoE/c001apk-compose/HEAD/app/src/main/res/drawable-v1/coolapk_emotion_58_dogeyuanliangta.png -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/state/State.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.state 2 | 3 | /** 4 | * Created by bggRGjQaUbCoE on 2024/6/3 5 | */ 6 | sealed class State 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/TopicBean.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | 4 | 5 | data class TopicBean( 6 | val url: String, 7 | val title: String 8 | ) -------------------------------------------------------------------------------- /app/src/main/res/color/image_stroke.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/white_radius.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_oval_primary.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/AppItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import android.content.pm.PackageInfo 4 | 5 | data class AppItem( 6 | var label: String, 7 | val packageInfo: PackageInfo 8 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/OSSUploadPrepareModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | 4 | data class OSSUploadPrepareModel( 5 | val name: String, 6 | val resolution: String, 7 | val md5: String, 8 | ) -------------------------------------------------------------------------------- /app/src/main/res/values-v31/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @android:color/system_accent1_0 4 | @android:color/system_accent1_600 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/round_corners_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values-night-v31/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | @android:color/system_accent1_800 4 | @android:color/system_accent1_200 5 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/PostReplyResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | class PostReplyResponse( 4 | val status: Int?, 5 | val message: String?, 6 | val messageStatus: String?, 7 | val data: TotalReplyResponse.Data? 8 | ) -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | c001apk-compose 3 | Home 4 | Message 5 | Settings 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/HomeMenu.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class HomeMenu( 8 | var position: Int, 9 | @PrimaryKey 10 | var title: String, 11 | var isEnable: Boolean 12 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/DeviceInfo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | data class DeviceInfo( 4 | val deviceId: String, 5 | val mac: String, 6 | val manufacturer: String, 7 | val brand: String, 8 | val model: String, 9 | val display: String, 10 | val oaid: String 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/StringEntity.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class StringEntity( 8 | @PrimaryKey(autoGenerate = false) 9 | var data: String, 10 | var id: Long = System.currentTimeMillis() 11 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_emoji.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/providable/LocalUserPreferences.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.providable 2 | 3 | import androidx.compose.runtime.staticCompositionLocalOf 4 | import com.example.c001apk.compose.logic.datastore.UserPreferencesCompat 5 | 6 | val LocalUserPreferences = staticCompositionLocalOf { UserPreferencesCompat.default() } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/LoginResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | data class LoginResponse( 4 | val status: Int?, 5 | val messageStatus: Int?, 6 | val message: String?, 7 | val uid: String?, 8 | val username: String?, 9 | val token: String?, 10 | val refreshToken: String? 11 | ) 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/UpdateCheckItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.parcelize.Parcelize 5 | 6 | /** 7 | * Created by bggRGjQaUbCoE on 2024/6/12 8 | */ 9 | @Parcelize 10 | data class UpdateCheckItem( 11 | val key: String, 12 | val value: String, 13 | ) : Parcelable -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | local.properties 16 | *.log 17 | .idea 18 | .kotlin 19 | /coilimageloader 20 | /mojito 21 | /SketchImageViewLoader 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_emoji_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/anim/indicator_animator.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/state/FooterState.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.state 2 | 3 | /** 4 | * Created by bggRGjQaUbCoE on 2024/6/3 5 | */ 6 | sealed class FooterState : State(){ 7 | data object Loading : FooterState() 8 | data object End : FooterState() 9 | data object Success : FooterState() 10 | data class Error(val errMsg: String) : FooterState() 11 | } -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_bottom_sheet_slide_down.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/anim_bottom_sheet_slide_up.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/indicator_animator_reverse.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/RecentAtUser.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class RecentAtUser( 8 | var id: Long = System.currentTimeMillis(), 9 | val group: String = "recent", 10 | val avatar: String, 11 | @PrimaryKey(autoGenerate = false) 12 | val username: String, 13 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/LoadUrlResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | data class LoadUrlResponse( 4 | val status: Int?, 5 | val error: Int?, 6 | val message: String?, 7 | val data: Data? 8 | ) { 9 | data class Data( 10 | val title: String, 11 | val logo: String?, 12 | val url: String, 13 | val description: String, 14 | ) 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/FeedContentResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.parcelize.Parcelize 5 | 6 | @Parcelize 7 | data class FeedContentResponse( 8 | val status: Int?, 9 | val error: Int?, 10 | val message: String?, 11 | val messageStatus: String?, 12 | val data: HomeFeedResponse.Data?, 13 | ) : Parcelable 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/FeedArticleContentBean.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import java.util.UUID 4 | 5 | data class FeedArticleContentBean( 6 | val key: String = UUID.randomUUID().toString(), 7 | val type: String?, 8 | val message: String?, 9 | val url: String?, 10 | val description: String?, 11 | val title: String?, 12 | val subTitle: String?, 13 | val logo: String?, 14 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_photo.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/state/LoadingState.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.state 2 | 3 | /** 4 | * Created by bggRGjQaUbCoE on 2024/6/3 5 | */ 6 | sealed class LoadingState : State() { 7 | data object Loading : LoadingState() 8 | data object Empty : LoadingState() 9 | data class Success(val response: T) : LoadingState() 10 | data class Error(val errMsg: String) : LoadingState() 11 | } -------------------------------------------------------------------------------- /app/src/test/java/com/example/c001apk/compose/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose 2 | 3 | import org.junit.Assert.assertEquals 4 | import org.junit.Test 5 | 6 | /** 7 | * Example local unit test, which will execute on the development machine (host). 8 | * 9 | * See [testing documentation](http://d.android.com/tools/testing). 10 | */ 11 | class ExampleUnitTest { 12 | @Test 13 | fun addition_isCorrect() { 14 | assertEquals(4, 2 + 2) 15 | } 16 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_tag_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/database/HomeMenuDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.database 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.example.c001apk.compose.logic.dao.HomeMenuDao 6 | import com.example.c001apk.compose.logic.model.HomeMenu 7 | 8 | @Database(version = 1, entities = [HomeMenu::class]) 9 | abstract class HomeMenuDatabase : RoomDatabase() { 10 | abstract fun homeMenuDao(): HomeMenuDao 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/LikeResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.annotations.JsonAdapter 4 | 5 | data class LikeResponse( 6 | @JsonAdapter(LikeAdapterFactory::class) 7 | val data: Data?, 8 | val status: Int?, 9 | val error: Int?, 10 | val message: String?, 11 | val messageStatus: String?, 12 | ) { 13 | data class Data( 14 | val count: String?, 15 | val follow: Int? = 0, 16 | ) 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/database/RecentAtUserDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.database 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.example.c001apk.compose.logic.dao.RecentAtUserDao 6 | import com.example.c001apk.compose.logic.model.RecentAtUser 7 | 8 | @Database(version = 1, entities = [RecentAtUser::class]) 9 | abstract class RecentAtUserDatabase : RoomDatabase() { 10 | abstract fun recentAtUserDao(): RecentAtUserDao 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/database/StringEntityDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.database 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.example.c001apk.compose.logic.dao.StringEntityDao 6 | import com.example.c001apk.compose.logic.model.StringEntity 7 | 8 | @Database(version = 1, entities = [StringEntity::class]) 9 | abstract class StringEntityDatabase : RoomDatabase() { 10 | abstract fun stringEntityDao(): StringEntityDao 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/database/HistoryFavoriteDatabase.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.database 2 | 3 | import androidx.room.Database 4 | import androidx.room.RoomDatabase 5 | import com.example.c001apk.compose.logic.dao.HistoryFavoriteDao 6 | import com.example.c001apk.compose.logic.model.FeedEntity 7 | 8 | 9 | @Database(version = 1, entities = [FeedEntity::class]) 10 | abstract class HistoryFavoriteDatabase : RoomDatabase() { 11 | abstract fun historyFavoriteDao(): HistoryFavoriteDao 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/FeedEntity.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import androidx.room.Entity 4 | import androidx.room.PrimaryKey 5 | 6 | @Entity 7 | data class FeedEntity( 8 | @PrimaryKey(autoGenerate = false) 9 | val id: String, 10 | val uid: String, 11 | val uname: String, 12 | val avatar: String, 13 | val device: String, 14 | val message: String, 15 | val pubDate: String, 16 | val time: String = System.currentTimeMillis().toString(), 17 | ) -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_bg_trans.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/xml/backup_rules.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_image_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_emoji.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_emoji_indicator_selected.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/theme/Color.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.theme 2 | 3 | import androidx.compose.material3.MaterialTheme 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.graphics.Color 6 | 7 | val Purple80 = Color(0xFFD0BCFF) 8 | val PurpleGrey80 = Color(0xFFCCC2DC) 9 | val Pink80 = Color(0xFFEFB8C8) 10 | 11 | val Purple40 = Color(0xFF6650a4) 12 | val PurpleGrey40 = Color(0xFF625b71) 13 | val Pink40 = Color(0xFF7D5260) 14 | 15 | @Composable 16 | fun cardBg() = MaterialTheme.colorScheme.surfaceContainer 17 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | #FFFFFF 11 | #607D8B 12 | #0D000000 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_bg_12_trans.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/xml/data_extraction_rules.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_keyboard_hide_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_backspace_24.xml: -------------------------------------------------------------------------------- 1 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/layout/dialog_refresh.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/CheckCountResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class CheckCountResponse( 6 | val status: Int?, 7 | val message: String?, 8 | val messageStatus: String?, 9 | val data: Data? 10 | ) { 11 | 12 | data class Data( 13 | val notification: Int, 14 | @SerializedName("contacts_follow") 15 | val contactsFollow: Int, 16 | val message: Int, 17 | val atme: Int, 18 | val atcommentme: Int, 19 | val commentme: Int, 20 | val feedlike: Int, 21 | val badge: Int, 22 | val dateline: String 23 | ) 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/UpdateCheckResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | 4 | 5 | data class UpdateCheckResponse(val data: List) { 6 | data class Data( 7 | val id: Int, 8 | val title: String, 9 | val shorttitle: String, 10 | val logo: String, 11 | val apkversionname: String, 12 | val apkversioncode: Long, 13 | val apksize: String, 14 | val lastupdate: Long, 15 | val packageName: String, 16 | val changelog: String, 17 | val pkg_bit_type: Int, 18 | var localVersionName: String?, 19 | var localVersionCode: Long?, 20 | var expand: Boolean = false, 21 | ) 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_reply.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_with_alpha.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 11 | 16 | 17 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_alternate_email_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/Button.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component 2 | 3 | import androidx.compose.material.icons.Icons 4 | import androidx.compose.material.icons.automirrored.outlined.ArrowBack 5 | import androidx.compose.material3.Icon 6 | import androidx.compose.material3.IconButton 7 | import androidx.compose.runtime.Composable 8 | import com.example.c001apk.compose.util.composeClick 9 | 10 | /** 11 | * Created by bggRGjQaUbCoE on 2024/6/2 12 | */ 13 | @Composable 14 | fun BackButton( 15 | onBackClick: () -> Unit 16 | ) { 17 | IconButton(onClick = composeClick { 18 | onBackClick() 19 | }) { 20 | Icon( 21 | imageVector = Icons.AutoMirrored.Outlined.ArrowBack, 22 | contentDescription = null 23 | ) 24 | } 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/CreateFeedResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class CreateFeedResponse( 6 | val status: Int?, 7 | val error: Int?, 8 | val message: String?, 9 | val messageStatus: String?, 10 | val data: Data? 11 | ) { 12 | data class Data( 13 | val status: Int?, 14 | val error: Int?, 15 | val messageStatus: String?, 16 | val id: String?, 17 | val type: String?, 18 | val message: String?, 19 | val pic: String, 20 | @SerializedName("device_title") val deviceTitle: String?, 21 | @SerializedName("message_signature") val messageSignature: String?, 22 | val picArr: List?, 23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_keyboard_show_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/example/c001apk/compose/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import androidx.test.platform.app.InstrumentationRegistry 5 | import org.junit.Assert.assertEquals 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | /** 10 | * Instrumented test, which will execute on an Android device. 11 | * 12 | * See [testing documentation](http://d.android.com/tools/testing). 13 | */ 14 | @RunWith(AndroidJUnit4::class) 15 | class ExampleInstrumentedTest { 16 | @Test 17 | fun useAppContext() { 18 | // Context of the app under test. 19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 20 | assertEquals("com.example.c001apk.compose", appContext.packageName) 21 | } 22 | } -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | google { 4 | content { 5 | includeGroupByRegex("com\\.android.*") 6 | includeGroupByRegex("com\\.google.*") 7 | includeGroupByRegex("androidx.*") 8 | } 9 | } 10 | mavenCentral() 11 | gradlePluginPortal() 12 | } 13 | } 14 | dependencyResolutionManagement { 15 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) 16 | repositories { 17 | google() 18 | mavenCentral() 19 | maven ("https://jitpack.io") 20 | maven("https://oss.sonatype.org/content/repositories/public") 21 | gradlePluginPortal() 22 | } 23 | } 24 | 25 | rootProject.name = "c001apk-compose" 26 | include(":app", ":mojito", ":SketchImageViewLoader", ":coilimageLoader") 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_note_alt_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/FooterCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component 2 | 3 | import androidx.compose.foundation.lazy.LazyListScope 4 | import androidx.compose.ui.Modifier 5 | import com.example.c001apk.compose.logic.state.FooterState 6 | import com.example.c001apk.compose.ui.component.cards.LoadingCard 7 | 8 | /** 9 | * Created by bggRGjQaUbCoE on 2024/6/10 10 | */ 11 | fun LazyListScope.FooterCard( 12 | modifier: Modifier = Modifier, 13 | footerState: FooterState, 14 | loadMore: () -> Unit, 15 | isFeed: Boolean = false, 16 | ) { 17 | item(key = "footer") { 18 | LoadingCard( 19 | modifier = modifier, 20 | state = footerState, 21 | onClick = if (footerState is FooterState.Error) loadMore 22 | else null, 23 | isFeed = isFeed, 24 | ) 25 | } 26 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/settings/SwitchListItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.settings 2 | 3 | import androidx.compose.material3.Switch 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.graphics.vector.ImageVector 6 | 7 | @Composable 8 | fun SwitchListItem( 9 | value: Boolean, 10 | leadingImageVector: ImageVector, 11 | headlineText: String, 12 | supportingText: String? = null, 13 | onValueChanged: (value: Boolean) -> Unit 14 | ) { 15 | BasicListItem( 16 | leadingImageVector = leadingImageVector, 17 | headlineText = headlineText, 18 | supportingText = supportingText, 19 | trailingContent = { 20 | Switch( 21 | checked = value, 22 | onCheckedChange = { 23 | onValueChanged(it) 24 | }, 25 | ) 26 | } 27 | ) { 28 | onValueChanged(!value) 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/webview/WebViewViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.webview 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import com.example.c001apk.compose.logic.repository.UserPreferencesRepository 6 | import dagger.hilt.android.lifecycle.HiltViewModel 7 | import kotlinx.coroutines.launch 8 | import javax.inject.Inject 9 | 10 | /** 11 | * Created by bggRGjQaUbCoE on 2024/6/11 12 | */ 13 | @HiltViewModel 14 | class WebViewViewModel @Inject constructor( 15 | private val userPreferencesRepository: UserPreferencesRepository 16 | ) : ViewModel() { 17 | 18 | fun setIsLogin(uid: String, username: String, token: String) { 19 | viewModelScope.launch { 20 | userPreferencesRepository.apply { 21 | setUid(uid) 22 | setUsername(username) 23 | setToken(token) 24 | setIsLogin(true) 25 | } 26 | } 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/cards/ChatTimeCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.cards 2 | 3 | import androidx.compose.foundation.layout.fillMaxWidth 4 | import androidx.compose.foundation.layout.padding 5 | import androidx.compose.material3.MaterialTheme 6 | import androidx.compose.material3.Text 7 | import androidx.compose.runtime.Composable 8 | import androidx.compose.ui.Modifier 9 | import androidx.compose.ui.text.style.TextAlign 10 | import androidx.compose.ui.unit.dp 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/19 14 | */ 15 | @Composable 16 | fun ChatTimeCard( 17 | modifier: Modifier = Modifier, 18 | title: String 19 | ) { 20 | 21 | Text( 22 | text = title, 23 | modifier = modifier 24 | .fillMaxWidth() 25 | .padding(12.dp), 26 | color = MaterialTheme.colorScheme.outline, 27 | style = MaterialTheme.typography.bodySmall, 28 | textAlign = TextAlign.Center, 29 | ) 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/repository/HomeMenuRepo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.repository 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.example.c001apk.compose.logic.dao.HomeMenuDao 5 | import com.example.c001apk.compose.logic.model.HomeMenu 6 | import javax.inject.Inject 7 | import javax.inject.Singleton 8 | 9 | @Singleton 10 | class HomeMenuRepo @Inject constructor( 11 | private val homeMenuDao: HomeMenuDao, 12 | ) { 13 | 14 | fun loadAllListLive(): LiveData> { 15 | return homeMenuDao.loadAllListLive() 16 | } 17 | 18 | suspend fun insert(homeMenu: HomeMenu) { 19 | homeMenuDao.insert(homeMenu) 20 | } 21 | 22 | suspend fun insertList(list: List) { 23 | homeMenuDao.insertList(list) 24 | } 25 | 26 | suspend fun updateList(list: List) { 27 | homeMenuDao.updateList(list) 28 | } 29 | 30 | suspend fun deleteAll() { 31 | homeMenuDao.deleteAll() 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/OSSUploadPrepareResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | data class OSSUploadPrepareResponse( 4 | val status: Int?, 5 | val error: Int?, 6 | val message: String?, 7 | val messageStatus: String?, 8 | val data: Data? 9 | ) { 10 | data class Data( 11 | val fileInfo: List, 12 | val uploadPrepareInfo: UploadPrepareInfo 13 | ) 14 | 15 | data class FileInfo( 16 | val name: String, 17 | val resolution: String, 18 | val md5: String, 19 | val url: String, 20 | val uploadFileName: String 21 | ) 22 | 23 | data class UploadPrepareInfo( 24 | val accessKeySecret: String, 25 | val accessKeyId: String, 26 | val securityToken: String, 27 | val expiration: String, 28 | val uploadImagePrefix: String, 29 | val endPoint: String, 30 | val bucket: String, 31 | val callbackUrl: String, 32 | ) 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/datastore/UserPreferencesSerializer.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.datastore 2 | 3 | import androidx.datastore.core.CorruptionException 4 | import androidx.datastore.core.Serializer 5 | import com.example.c001apk.compose.UserPreferences 6 | import com.google.protobuf.InvalidProtocolBufferException 7 | import java.io.InputStream 8 | import java.io.OutputStream 9 | import javax.inject.Inject 10 | 11 | class UserPreferencesSerializer @Inject constructor() : Serializer { 12 | override val defaultValue = UserPreferencesCompat.default() 13 | 14 | override suspend fun readFrom(input: InputStream) = 15 | try { 16 | UserPreferences.parseFrom(input).let(::UserPreferencesCompat) 17 | } catch (e: InvalidProtocolBufferException) { 18 | throw CorruptionException("cannot read proto", e) 19 | } 20 | 21 | override suspend fun writeTo(t: UserPreferencesCompat, output: OutputStream) { 22 | t.toProto().writeTo(output) 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/outline_emoji_emotions_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 13 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/util/NetWorkUtil.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.util 2 | 3 | import android.content.Context 4 | import android.net.ConnectivityManager 5 | import android.net.Network 6 | import android.net.NetworkCapabilities 7 | import com.example.c001apk.compose.c001Application 8 | 9 | /** 10 | * Created by bggRGjQaUbCoE on 2024/6/4 11 | */ 12 | object NetWorkUtil { 13 | 14 | fun isWifiConnected(): Boolean { 15 | val cm = c001Application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager 16 | val network: Network? = cm.activeNetwork 17 | if (network != null) { 18 | val nc = cm.getNetworkCapabilities(network) 19 | nc?.let { 20 | if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 21 | return true 22 | } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 23 | return false 24 | } 25 | } 26 | } 27 | return false 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/CheckResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class CheckResponse( 6 | val status: Int?, 7 | val message: String?, 8 | val messageStatus: String?, 9 | val data: Data? 10 | ) { 11 | 12 | data class Data( 13 | val id: String?, 14 | val status: Int, 15 | @SerializedName("message_status") val messageStatus: Int?, 16 | val uid: String, 17 | val username: String, 18 | val token: String, 19 | val refreshToken: String, 20 | val userAvatar: String, 21 | val notifyCount: NotifyCount, 22 | ) 23 | 24 | data class NotifyCount( 25 | val notification: Int, 26 | @SerializedName("contacts_follow") val contactsFollow: Int, 27 | val message: Int, 28 | val atme: Int, 29 | val atcommentme: Int, 30 | val commentme: Int, 31 | val feedlike: Int, 32 | val badge: Int, 33 | val dateline: String 34 | ) 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/view/MyURLSpan.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.view 2 | 3 | import android.text.TextPaint 4 | import android.text.style.ClickableSpan 5 | import android.view.View 6 | 7 | /** 8 | * Created by bggRGjQaUbCoE on 2024/6/4 9 | */ 10 | class MyURLSpan( 11 | private val mUrl: String, 12 | private val linkTextColor: Int, 13 | private val onShowTotalReply: (() -> Unit)? = null, 14 | private val onOpenLink: (String, String?) -> Unit, 15 | private val onShowImages: (String) -> Unit, 16 | ) : 17 | ClickableSpan() { 18 | 19 | override fun onClick(widget: View) { 20 | if (mUrl.isNotEmpty()) { 21 | when { 22 | mUrl.contains("/feed/replyList") -> onShowTotalReply?.let { it() } 23 | 24 | mUrl.contains("image.coolapk.com") -> onShowImages(mUrl) 25 | 26 | else -> onOpenLink(mUrl, null) 27 | } 28 | } 29 | } 30 | 31 | override fun updateDrawState(ds: TextPaint) { 32 | super.updateDrawState(ds) 33 | ds.color = linkTextColor 34 | ds.isUnderlineText = false 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/home/topic/HomeTopicViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.home.topic 2 | 3 | import com.example.c001apk.compose.logic.repository.BlackListRepo 4 | import com.example.c001apk.compose.logic.repository.NetworkRepo 5 | import com.example.c001apk.compose.ui.base.BaseViewModel 6 | import dagger.assisted.Assisted 7 | import dagger.assisted.AssistedFactory 8 | import dagger.assisted.AssistedInject 9 | import dagger.hilt.android.lifecycle.HiltViewModel 10 | 11 | /** 12 | * Created by bggRGjQaUbCoE on 2024/6/11 13 | */ 14 | @HiltViewModel(assistedFactory = HomeTopicViewModel.ViewModelFactory::class) 15 | class HomeTopicViewModel @AssistedInject constructor( 16 | @Assisted val url: String, 17 | networkRepo: NetworkRepo, 18 | blackListRepo: BlackListRepo, 19 | ) : BaseViewModel(networkRepo, blackListRepo) { 20 | 21 | @AssistedFactory 22 | interface ViewModelFactory { 23 | fun create(url: String): HomeTopicViewModel 24 | } 25 | 26 | init { 27 | fetchData() 28 | } 29 | 30 | override suspend fun customFetchData() = networkRepo.getProductList(url) 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/di/DataStoreModule.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.di 2 | 3 | import android.content.Context 4 | import androidx.datastore.core.DataStore 5 | import androidx.datastore.core.DataStoreFactory 6 | import androidx.datastore.dataStoreFile 7 | import com.example.c001apk.compose.logic.datastore.UserPreferencesCompat 8 | import com.example.c001apk.compose.logic.datastore.UserPreferencesSerializer 9 | import dagger.Module 10 | import dagger.Provides 11 | import dagger.hilt.InstallIn 12 | import dagger.hilt.android.qualifiers.ApplicationContext 13 | import dagger.hilt.components.SingletonComponent 14 | import javax.inject.Singleton 15 | 16 | @Module 17 | @InstallIn(SingletonComponent::class) 18 | object DataStoreModule { 19 | @Provides 20 | @Singleton 21 | fun providesUserPreferencesDataStore( 22 | @ApplicationContext context: Context, 23 | userPreferencesSerializer: UserPreferencesSerializer 24 | ): DataStore = 25 | DataStoreFactory.create( 26 | serializer = userPreferencesSerializer 27 | ) { 28 | context.dataStoreFile("user_preferences.pb") 29 | } 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/theme/Type.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.theme 2 | 3 | import androidx.compose.material3.Typography 4 | import androidx.compose.ui.text.TextStyle 5 | import androidx.compose.ui.text.font.FontFamily 6 | import androidx.compose.ui.text.font.FontWeight 7 | import androidx.compose.ui.unit.sp 8 | 9 | // Set of Material typography styles to start with 10 | val Typography = Typography( 11 | bodyLarge = TextStyle( 12 | fontFamily = FontFamily.Default, 13 | fontWeight = FontWeight.Normal, 14 | fontSize = 16.sp, 15 | lineHeight = 24.sp, 16 | letterSpacing = 0.5.sp 17 | ) 18 | /* Other default text styles to override 19 | titleLarge = TextStyle( 20 | fontFamily = FontFamily.Default, 21 | fontWeight = FontWeight.Normal, 22 | fontSize = 22.sp, 23 | lineHeight = 28.sp, 24 | letterSpacing = 0.sp 25 | ), 26 | labelSmall = TextStyle( 27 | fontFamily = FontFamily.Default, 28 | fontWeight = FontWeight.Medium, 29 | fontSize = 11.sp, 30 | lineHeight = 16.sp, 31 | letterSpacing = 0.5.sp 32 | ) 33 | */ 34 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/TotalReplyResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | 4 | import com.google.gson.annotations.SerializedName 5 | 6 | data class TotalReplyResponse( 7 | val status: Int?, 8 | val error: Int?, 9 | val message: String?, 10 | val data: List? 11 | ) { 12 | 13 | data class Data( 14 | var lastupdate: Long?, 15 | @SerializedName("extra_key") val extraKey: String?, 16 | val entityType: String?, 17 | val id: String, 18 | val ruid: String?, 19 | val uid: String, 20 | val feedUid: String?, 21 | var username: String, 22 | val rusername: String?, 23 | var message: String, 24 | val pic: String?, 25 | val picArr: List?, 26 | val dateline: Long, 27 | var likenum: String, 28 | val replynum: String, 29 | val userAvatar: String, 30 | var replyRows: MutableList?, 31 | val replyRowsMore: Int?, 32 | val userAction: UserAction?, 33 | val userInfo: UserInfo 34 | ) 35 | 36 | data class UserAction(var like: Int) 37 | 38 | data class UserInfo(val username: String) 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/MessageListResponse.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | data class MessageListResponse( 6 | val status: Int?, 7 | val message: String?, 8 | val messageStatus: String?, 9 | val data: List? 10 | ) { 11 | data class Data( 12 | val title: String?, 13 | val id: String?, 14 | val ukey: String?, 15 | val uid: String?, 16 | val username: String?, 17 | val fromuid: String?, 18 | val fromusername: String?, 19 | val islast: Int?, 20 | val isnew: Int?, 21 | val message: String?, 22 | @SerializedName("message_pic") 23 | val messagePic: String?, 24 | val dateline: Long?, 25 | val entityType: String?, 26 | val entityId: String?, 27 | val messageUid: String?, 28 | val messageUsername: String?, 29 | val userAvatar: String?, 30 | val fromUserAvatar: String?, 31 | val messageUserAvatar: String?, 32 | var unreadNum: Int?, 33 | @SerializedName("is_top") 34 | val isTop: Int?, 35 | val entityTemplate: String?, 36 | ) 37 | } -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/dao/HistoryFavoriteDao.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.dao 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.Dao 5 | import androidx.room.Insert 6 | import androidx.room.Query 7 | import com.example.c001apk.compose.logic.model.FeedEntity 8 | import kotlinx.coroutines.flow.Flow 9 | 10 | 11 | @Dao 12 | interface HistoryFavoriteDao { 13 | 14 | @Insert 15 | suspend fun insert(data: FeedEntity) 16 | 17 | @Query("SELECT * FROM FeedEntity ORDER BY time DESC") 18 | suspend fun loadAllList(): List 19 | 20 | @Query("SELECT * FROM FeedEntity ORDER BY time DESC") 21 | fun loadAllListLive(): LiveData> 22 | 23 | @Query("SELECT * FROM FeedEntity ORDER BY time DESC") 24 | fun loadAllListFlow(): Flow> 25 | 26 | @Query("SELECT 1 FROM FeedEntity WHERE id = :id LIMIT 1") 27 | suspend fun isExist(id: String): Boolean 28 | 29 | @Query("DELETE FROM FeedEntity WHERE id = :id") 30 | suspend fun delete(id: String) 31 | 32 | @Query("DELETE FROM FeedEntity") 33 | suspend fun deleteAll() 34 | 35 | @Query("DELETE FROM FeedEntity WHERE uid = :uid") 36 | suspend fun deleteByUid(uid:String) 37 | 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/dao/HomeMenuDao.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.dao 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.Dao 5 | import androidx.room.Insert 6 | import androidx.room.Query 7 | import androidx.room.Update 8 | import com.example.c001apk.compose.logic.model.HomeMenu 9 | import kotlinx.coroutines.flow.Flow 10 | 11 | 12 | @Dao 13 | interface HomeMenuDao { 14 | 15 | @Insert 16 | suspend fun insert(menu: HomeMenu) 17 | 18 | @Insert 19 | suspend fun insertList(list: List) 20 | 21 | @Query("SELECT * FROM HomeMenu ORDER BY position ASC") 22 | suspend fun loadAllList(): List 23 | 24 | @Query("SELECT * FROM HomeMenu ORDER BY position ASC") 25 | fun loadAllListLive(): LiveData> 26 | 27 | @Query("SELECT * FROM HomeMenu ORDER BY position ASC") 28 | fun loadAllListFlow(): Flow> 29 | 30 | @Query("SELECT 1 FROM HomeMenu WHERE title = :title LIMIT 1") 31 | suspend fun isExist(title: String): Boolean 32 | 33 | @Query("DELETE FROM HomeMenu WHERE title = :title") 34 | suspend fun delete(title: String) 35 | 36 | @Query("DELETE FROM HomeMenu") 37 | suspend fun deleteAll() 38 | 39 | @Update 40 | suspend fun updateList(list:List) 41 | 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/view/CenteredImageSpan.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.view 2 | 3 | import android.graphics.Canvas 4 | import android.graphics.Paint 5 | import android.graphics.drawable.Drawable 6 | import android.text.style.ImageSpan 7 | 8 | class CenteredImageSpan(drawableRes: Drawable, private val size: Int, private val group: String?) : 9 | ImageSpan(drawableRes) { 10 | 11 | override fun getSize( 12 | paint: Paint, 13 | text: CharSequence?, 14 | start: Int, 15 | end: Int, 16 | fm: Paint.FontMetricsInt? 17 | ): Int { 18 | return if (group in listOf("[楼主]", "[层主]", "[置顶]")) 19 | super.getSize(paint, text, start, end, fm) 20 | else size 21 | } 22 | 23 | override fun draw( 24 | canvas: Canvas, text: CharSequence, 25 | start: Int, end: Int, x: Float, 26 | top: Int, y: Int, bottom: Int, paint: Paint 27 | ) { 28 | // image to draw 29 | val b = drawable 30 | // font metrics of text to be replaced 31 | val fm = paint.fontMetricsInt 32 | val transY = ((y + fm.descent + y + fm.ascent) / 2 33 | - b.bounds.bottom / 2) 34 | canvas.save() 35 | canvas.translate(x, transY.toFloat()) 36 | b.draw(canvas) 37 | canvas.restore() 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/cards/TextCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.cards 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Box 5 | import androidx.compose.foundation.layout.fillMaxWidth 6 | import androidx.compose.foundation.layout.height 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.material3.Text 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import androidx.compose.ui.draw.clip 14 | import androidx.compose.ui.unit.dp 15 | import com.example.c001apk.compose.ui.theme.cardBg 16 | 17 | /** 18 | * Created by bggRGjQaUbCoE on 2024/6/15 19 | */ 20 | @Composable 21 | fun TextCard( 22 | modifier: Modifier = Modifier, 23 | text: String 24 | ) { 25 | Box( 26 | modifier = modifier 27 | .fillMaxWidth() 28 | .height(80.dp) 29 | .clip(MaterialTheme.shapes.medium) 30 | .background(cardBg()), 31 | contentAlignment = Alignment.Center 32 | ) { 33 | Text( 34 | modifier = Modifier.padding(16.dp), 35 | text = text, 36 | color = MaterialTheme.colorScheme.outline, 37 | ) 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/C001Application.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose 2 | 3 | import android.app.Application 4 | import coil.Coil 5 | import coil.ImageLoader 6 | import com.example.c001apk.compose.util.dp 7 | import dagger.hilt.android.HiltAndroidApp 8 | import me.zhanghai.android.appiconloader.coil.AppIconFetcher 9 | import me.zhanghai.android.appiconloader.coil.AppIconKeyer 10 | import net.mikaelzero.coilimageloader.CoilImageLoader 11 | import net.mikaelzero.mojito.Mojito 12 | import net.mikaelzero.mojito.view.sketch.SketchImageLoadFactory 13 | 14 | /** 15 | * Created by bggRGjQaUbCoE on 2024/5/29 16 | */ 17 | lateinit var c001Application: C001Application 18 | 19 | @HiltAndroidApp 20 | class C001Application : Application() { 21 | 22 | override fun onCreate() { 23 | super.onCreate() 24 | 25 | c001Application = this 26 | 27 | Coil.setImageLoader( 28 | ImageLoader.Builder(this) 29 | .crossfade(true) 30 | .components { 31 | add(AppIconKeyer()) 32 | add(AppIconFetcher.Factory(48.dp, false, this@C001Application)) 33 | } 34 | .build() 35 | ) 36 | 37 | Mojito.initialize( 38 | CoilImageLoader.with(this), 39 | SketchImageLoadFactory() 40 | ) 41 | 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. For more details, visit 12 | # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects 13 | # org.gradle.parallel=true 14 | # AndroidX package structure to make it clearer which packages are bundled with the 15 | # Android operating system, and which are packaged with your app's APK 16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 17 | android.useAndroidX=true 18 | # Kotlin code style for this project: "official" or "obsolete": 19 | kotlin.code.style=official 20 | # Enables namespacing of each library's R class so that its R class includes only the 21 | # resources declared in the library itself and none from the library's dependencies, 22 | # thereby reducing the size of the R class for that library 23 | android.nonTransitiveRClass=true -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/FeedAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.example.c001apk.compose.logic.model.HomeFeedResponse.Feed 4 | import com.google.gson.Gson 5 | import com.google.gson.TypeAdapter 6 | import com.google.gson.TypeAdapterFactory 7 | import com.google.gson.reflect.TypeToken 8 | import com.google.gson.stream.JsonReader 9 | import com.google.gson.stream.JsonToken 10 | import com.google.gson.stream.JsonWriter 11 | import java.io.IOException 12 | 13 | object FeedAdapterFactory : TypeAdapterFactory { 14 | override fun create(gson: Gson, type: TypeToken): TypeAdapter { 15 | return FeedAdapter(gson) as TypeAdapter 16 | } 17 | } 18 | 19 | class FeedAdapter(private val gson: Gson) : TypeAdapter() { 20 | @Throws(IOException::class) 21 | override fun write(jsonWriter: JsonWriter, feed: Feed?) { 22 | throw RuntimeException("Not implemented") 23 | } 24 | 25 | @Throws(IOException::class) 26 | override fun read(jsonReader: JsonReader): Feed? { 27 | return when (jsonReader.peek()) { 28 | JsonToken.NUMBER -> Feed(id = jsonReader.nextInt().toString()) 29 | 30 | JsonToken.BEGIN_OBJECT -> 31 | gson.fromJson(jsonReader, Feed::class.java) 32 | 33 | else -> throw RuntimeException("Expected object or int, not " + jsonReader.peek()) 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/repository/RecentAtUserRepo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.repository 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.example.c001apk.compose.logic.dao.RecentAtUserDao 5 | import com.example.c001apk.compose.logic.model.RecentAtUser 6 | import javax.inject.Inject 7 | import javax.inject.Singleton 8 | 9 | @Singleton 10 | class RecentAtUserRepo @Inject constructor( 11 | private val recentAtUserDao: RecentAtUserDao, 12 | ) { 13 | 14 | fun loadAllListLive(): LiveData> { 15 | return recentAtUserDao.loadAllListLive() 16 | } 17 | 18 | suspend fun insertUser(user: RecentAtUser) { 19 | recentAtUserDao.insert(user) 20 | } 21 | 22 | suspend fun insertList(list: List) { 23 | recentAtUserDao.insertList(list) 24 | } 25 | 26 | suspend fun deleteUser(user: String) { 27 | recentAtUserDao.delete(user) 28 | } 29 | 30 | suspend fun deleteUser(user: RecentAtUser) { 31 | recentAtUserDao.delete(user) 32 | } 33 | 34 | suspend fun deleteAll() { 35 | recentAtUserDao.deleteAll() 36 | } 37 | 38 | suspend fun checkUser(username: String): Boolean { 39 | return recentAtUserDao.isExist(username) 40 | } 41 | 42 | suspend fun updateUser(username: String, newId: Long) { 43 | recentAtUserDao.updateUser(username, newId) 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/item_captcha.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | 24 | 25 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/cards/SearchHistoryCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.cards 2 | 3 | import androidx.compose.foundation.ExperimentalFoundationApi 4 | import androidx.compose.foundation.background 5 | import androidx.compose.foundation.combinedClickable 6 | import androidx.compose.foundation.layout.padding 7 | import androidx.compose.foundation.shape.RoundedCornerShape 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.material3.Text 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.draw.clip 13 | import androidx.compose.ui.unit.dp 14 | import com.example.c001apk.compose.ui.theme.cardBg 15 | 16 | /** 17 | * Created by bggRGjQaUbCoE on 2024/6/16 18 | */ 19 | @OptIn(ExperimentalFoundationApi::class) 20 | @Composable 21 | fun SearchHistoryCard( 22 | modifier: Modifier = Modifier, 23 | data: String, 24 | onSearch: () -> Unit, 25 | onDelete: () -> Unit, 26 | ) { 27 | 28 | Text( 29 | modifier = modifier 30 | .clip(RoundedCornerShape(20.dp)) 31 | .background(cardBg()) 32 | .combinedClickable( 33 | onClick = onSearch, 34 | onLongClick = onDelete 35 | ) 36 | .padding(horizontal = 10.dp, vertical = 4.dp), 37 | text = data, 38 | style = MaterialTheme.typography.titleSmall, 39 | ) 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_subauthor.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 13 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 13 | 14 | 17 | 18 | 21 | 22 | 32 | 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/model/LikeAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.model 2 | 3 | import com.google.gson.Gson 4 | import com.google.gson.TypeAdapter 5 | import com.google.gson.TypeAdapterFactory 6 | import com.google.gson.reflect.TypeToken 7 | import com.google.gson.stream.JsonReader 8 | import com.google.gson.stream.JsonToken 9 | import com.google.gson.stream.JsonWriter 10 | import java.io.IOException 11 | 12 | object LikeAdapterFactory : TypeAdapterFactory { 13 | override fun create(gson: Gson, type: TypeToken): TypeAdapter { 14 | return LikeAdapter(gson) as TypeAdapter 15 | } 16 | } 17 | 18 | class LikeAdapter(private val gson: Gson) : TypeAdapter() { 19 | @Throws(IOException::class) 20 | override fun write(jsonWriter: JsonWriter, feed: LikeResponse.Data?) { 21 | throw RuntimeException("Not implemented") 22 | } 23 | 24 | @Throws(IOException::class) 25 | override fun read(jsonReader: JsonReader): LikeResponse.Data? { 26 | return when (jsonReader.peek()) { 27 | JsonToken.NUMBER -> LikeResponse.Data(count = jsonReader.nextInt().toString()) 28 | 29 | JsonToken.STRING -> LikeResponse.Data(count = jsonReader.nextString()) 30 | 31 | JsonToken.BEGIN_OBJECT -> 32 | gson.fromJson(jsonReader, LikeResponse.Data::class.java) 33 | 34 | else -> throw RuntimeException("Expected object or int, not " + jsonReader.peek()) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/dyh/DyhContentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.dyh 2 | 3 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 4 | import com.example.c001apk.compose.logic.repository.BlackListRepo 5 | import com.example.c001apk.compose.logic.repository.NetworkRepo 6 | import com.example.c001apk.compose.ui.base.BaseViewModel 7 | import dagger.assisted.Assisted 8 | import dagger.assisted.AssistedFactory 9 | import dagger.assisted.AssistedInject 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/12 14 | */ 15 | @HiltViewModel(assistedFactory = DyhContentViewModel.ViewModelFactory::class) 16 | class DyhContentViewModel @AssistedInject constructor( 17 | @Assisted("id") val id: String, 18 | @Assisted("type") val type: String, 19 | networkRepo: NetworkRepo, 20 | blackListRepo: BlackListRepo, 21 | ) : BaseViewModel(networkRepo, blackListRepo) { 22 | 23 | @AssistedFactory 24 | interface ViewModelFactory { 25 | fun create( 26 | @Assisted("id") id: String, 27 | @Assisted("type") type: String, 28 | ): DyhContentViewModel 29 | } 30 | 31 | init { 32 | fetchData() 33 | } 34 | 35 | override suspend fun customFetchData() = networkRepo.getDyhDetail(id, type, page, lastItem) 36 | 37 | override fun handleLoadMore(response: List): List { 38 | return response.distinctBy { it.entityId } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/search/SearchViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.search 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import com.example.c001apk.compose.logic.model.StringEntity 6 | import com.example.c001apk.compose.logic.repository.SearchHistoryRepo 7 | import dagger.hilt.android.lifecycle.HiltViewModel 8 | import kotlinx.coroutines.Dispatchers 9 | import kotlinx.coroutines.flow.Flow 10 | import kotlinx.coroutines.launch 11 | import javax.inject.Inject 12 | 13 | /** 14 | * Created by bggRGjQaUbCoE on 2024/6/16 15 | */ 16 | @HiltViewModel 17 | class SearchViewModel @Inject constructor( 18 | private val searchHistoryRepo: SearchHistoryRepo 19 | ) : ViewModel() { 20 | 21 | val searchHistory: Flow> = searchHistoryRepo.loadAllListFlow() 22 | 23 | fun saveHistory(keyword: String) { 24 | viewModelScope.launch(Dispatchers.IO) { 25 | if (searchHistoryRepo.isExist(keyword)) { 26 | searchHistoryRepo.updateHistory(keyword) 27 | } else { 28 | searchHistoryRepo.saveHistory(keyword) 29 | } 30 | } 31 | } 32 | 33 | fun clearAll() { 34 | viewModelScope.launch(Dispatchers.IO) { 35 | searchHistoryRepo.deleteAllHistory() 36 | } 37 | } 38 | 39 | fun delete(keyword: String) { 40 | viewModelScope.launch(Dispatchers.IO) { 41 | searchHistoryRepo.deleteHistory(keyword) 42 | } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/item_emoji_child_viewpager.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 | 20 | 21 | 22 | 23 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/coolpic/CoolPicContentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.coolpic 2 | 3 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 4 | import com.example.c001apk.compose.logic.repository.BlackListRepo 5 | import com.example.c001apk.compose.logic.repository.NetworkRepo 6 | import com.example.c001apk.compose.ui.base.BaseViewModel 7 | import dagger.assisted.Assisted 8 | import dagger.assisted.AssistedFactory 9 | import dagger.assisted.AssistedInject 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/12 14 | */ 15 | @HiltViewModel(assistedFactory = CoolPicContentViewModel.ViewModelFactory::class) 16 | class CoolPicContentViewModel @AssistedInject constructor( 17 | @Assisted("title") val title: String, 18 | @Assisted("type") val type: String, 19 | networkRepo: NetworkRepo, 20 | blackListRepo: BlackListRepo, 21 | ) : BaseViewModel(networkRepo, blackListRepo) { 22 | 23 | @AssistedFactory 24 | interface ViewModelFactory { 25 | fun create( 26 | @Assisted("title") title: String, 27 | @Assisted("type") type: String, 28 | ): CoolPicContentViewModel 29 | } 30 | 31 | init { 32 | fetchData() 33 | } 34 | 35 | override suspend fun customFetchData() = networkRepo.getCoolPic(title, type, page, lastItem) 36 | 37 | override fun handleLoadMore(response: List): List { 38 | return response.distinctBy { it.entityId } 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/util/CookieUtil.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.util 2 | 3 | import com.example.c001apk.compose.constant.Constants.API_VERSION 4 | import com.example.c001apk.compose.constant.Constants.EMPTY_STRING 5 | import com.example.c001apk.compose.constant.Constants.VERSION_CODE 6 | import com.example.c001apk.compose.constant.Constants.VERSION_NAME 7 | 8 | /** 9 | * Created by bggRGjQaUbCoE on 2024/6/3 10 | */ 11 | object CookieUtil { 12 | 13 | var SESSID = EMPTY_STRING 14 | var isPreGetLoginParam = false 15 | var isGetLoginParam = false 16 | var isTryLogin = false 17 | var isGetCaptcha = false 18 | var isGetSmsLoginParam = false 19 | var isGetSmsToken = false 20 | 21 | var atme: Int? = null 22 | var atcommentme: Int? = null 23 | var feedlike: Int? = null 24 | var contacts_follow: Int? = null 25 | var message: Int? = null 26 | var notification: Int = 0 27 | 28 | var isLogin = false 29 | var szlmId = EMPTY_STRING 30 | var xAppDevice = EMPTY_STRING 31 | var uid = EMPTY_STRING 32 | var username = EMPTY_STRING 33 | var token = EMPTY_STRING 34 | var userAgent = EMPTY_STRING 35 | var sdkInt = EMPTY_STRING 36 | var versionName = VERSION_NAME 37 | var versionCode = VERSION_CODE 38 | var apiVersion = API_VERSION 39 | var imageQuality = 0 40 | var showEmoji = true 41 | var imageFilter = true 42 | var isDarkMode = false 43 | var showSquare = true 44 | var openInBrowser = false 45 | var recordHistory = true 46 | var materialYou = true 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/feed/reply/emoji/EmojiChildPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.feed.reply.emoji 2 | 3 | import android.view.Gravity 4 | import android.view.ViewGroup 5 | import android.widget.GridView 6 | import androidx.recyclerview.widget.RecyclerView 7 | import com.example.c001apk.compose.util.dp 8 | 9 | class EmojiChildPagerAdapter( 10 | private val emojiList: List>>, 11 | private val onClickEmoji: (String) -> Unit, 12 | private val onCountStart: () -> Unit, 13 | private val onCountStop: () -> Unit 14 | ) : RecyclerView.Adapter() { 15 | 16 | class ViewHolder(val view: GridView) : RecyclerView.ViewHolder(view) 17 | 18 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 19 | val view = GridView(parent.context).apply { 20 | layoutParams = ViewGroup.LayoutParams( 21 | ViewGroup.LayoutParams.MATCH_PARENT, 22 | ViewGroup.LayoutParams.MATCH_PARENT 23 | ).apply { 24 | gravity = Gravity.CENTER 25 | } 26 | numColumns = 7 27 | verticalSpacing = 4.dp 28 | } 29 | return ViewHolder(view) 30 | } 31 | 32 | override fun getItemCount() = emojiList.size 33 | 34 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 35 | holder.view.adapter = EmojiGridAdapter( 36 | emojiList[position].toList(), 37 | onClickEmoji, 38 | onCountStart, 39 | onCountStop 40 | ) 41 | } 42 | 43 | 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/feed/reply/emoji/EmojiPagerAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.feed.reply.emoji 2 | 3 | import android.view.LayoutInflater 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import androidx.recyclerview.widget.RecyclerView 7 | import androidx.viewpager2.widget.ViewPager2 8 | import com.example.c001apk.compose.R 9 | import com.example.c001apk.compose.view.circleindicator.CircleIndicator3 10 | 11 | class EmojiPagerAdapter( 12 | private val emojiList: List>>>, 13 | private val onClickEmoji: (String) -> Unit, 14 | private val onCountStart: () -> Unit, 15 | private val onCountStop: () -> Unit 16 | ) : RecyclerView.Adapter() { 17 | 18 | class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { 19 | val viewPager: ViewPager2 = view.findViewById(R.id.viewPager) 20 | val indicator: CircleIndicator3 = view.findViewById(R.id.indicator) 21 | } 22 | 23 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 24 | val view = LayoutInflater.from(parent.context).inflate( 25 | R.layout.item_emoji_child_viewpager, parent, false 26 | ) 27 | return ViewHolder(view) 28 | } 29 | 30 | override fun getItemCount() = emojiList.size 31 | 32 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 33 | holder.viewPager.adapter = EmojiChildPagerAdapter( 34 | emojiList[position], onClickEmoji, onCountStart, onCountStop 35 | ) 36 | holder.indicator.setViewPager(holder.viewPager) 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/topic/TopicContentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.topic 2 | 3 | import com.example.c001apk.compose.constant.Constants.EMPTY_STRING 4 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 5 | import com.example.c001apk.compose.logic.repository.BlackListRepo 6 | import com.example.c001apk.compose.logic.repository.NetworkRepo 7 | import com.example.c001apk.compose.ui.base.BaseViewModel 8 | import dagger.assisted.Assisted 9 | import dagger.assisted.AssistedFactory 10 | import dagger.assisted.AssistedInject 11 | import dagger.hilt.android.lifecycle.HiltViewModel 12 | 13 | /** 14 | * Created by bggRGjQaUbCoE on 2024/6/9 15 | */ 16 | @HiltViewModel(assistedFactory = TopicContentViewModel.ViewModelFactory::class) 17 | class TopicContentViewModel @AssistedInject constructor( 18 | @Assisted("url") var url: String, 19 | @Assisted("title") var title: String, 20 | networkRepo: NetworkRepo, 21 | blackListRepo: BlackListRepo, 22 | ) : BaseViewModel(networkRepo, blackListRepo) { 23 | 24 | @AssistedFactory 25 | interface ViewModelFactory { 26 | fun create( 27 | @Assisted("url") url: String, 28 | @Assisted("title") title: String, 29 | ): TopicContentViewModel 30 | } 31 | 32 | var sortType = ProductSortType.REPLY 33 | 34 | init { 35 | fetchData() 36 | } 37 | 38 | override suspend fun customFetchData() = 39 | networkRepo.getDataList(url, title, EMPTY_STRING, lastItem, page) 40 | 41 | override fun handleLoadMore(response: List): List { 42 | return response.distinctBy { it.entityId } 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/app/AppContentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.app 2 | 3 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 4 | import com.example.c001apk.compose.logic.repository.BlackListRepo 5 | import com.example.c001apk.compose.logic.repository.NetworkRepo 6 | import com.example.c001apk.compose.ui.base.BaseViewModel 7 | import dagger.assisted.Assisted 8 | import dagger.assisted.AssistedFactory 9 | import dagger.assisted.AssistedInject 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/10 14 | */ 15 | @HiltViewModel(assistedFactory = AppContentViewModel.ViewModelFactory::class) 16 | class AppContentViewModel @AssistedInject constructor( 17 | @Assisted("url") val url: String, 18 | @Assisted("appCommentTitle") val appCommentTitle: String, 19 | networkRepo: NetworkRepo, 20 | blackListRepo: BlackListRepo, 21 | ) : BaseViewModel(networkRepo, blackListRepo) { 22 | 23 | @AssistedFactory 24 | interface ViewModelFactory { 25 | fun create( 26 | @Assisted("url") url: String, 27 | @Assisted("appCommentTitle") appCommentTitle: String, 28 | ): AppContentViewModel 29 | } 30 | 31 | init { 32 | fetchData() 33 | } 34 | 35 | override suspend fun customFetchData() = 36 | networkRepo.getDataList( 37 | url, 38 | appCommentTitle, 39 | null, 40 | lastItem, 41 | page 42 | ) 43 | 44 | override fun handleLoadMore(response: List): List { 45 | return response.distinctBy { it.entityId } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/repository/SearchHistoryRepo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.repository 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.example.c001apk.compose.di.SearchHistory 5 | import com.example.c001apk.compose.logic.dao.StringEntityDao 6 | import com.example.c001apk.compose.logic.model.StringEntity 7 | import kotlinx.coroutines.flow.Flow 8 | import javax.inject.Inject 9 | import javax.inject.Singleton 10 | 11 | @Singleton 12 | class SearchHistoryRepo @Inject constructor( 13 | @SearchHistory 14 | private val searchHistoryDao: StringEntityDao, 15 | ) { 16 | 17 | fun loadAllListFlow(): Flow> { 18 | return searchHistoryDao.loadAllListFlow() 19 | } 20 | 21 | fun loadAllListLive(): LiveData> { 22 | return searchHistoryDao.loadAllListLive() 23 | } 24 | 25 | suspend fun insertHistory(history: StringEntity) { 26 | searchHistoryDao.insert(history) 27 | } 28 | 29 | suspend fun insertList(list: List) { 30 | searchHistoryDao.insertList(list) 31 | } 32 | 33 | suspend fun saveHistory(history: String) { 34 | searchHistoryDao.insert(StringEntity(history)) 35 | } 36 | 37 | suspend fun deleteHistory(history: String) { 38 | searchHistoryDao.delete(history) 39 | } 40 | 41 | suspend fun deleteAllHistory() { 42 | searchHistoryDao.deleteAll() 43 | } 44 | 45 | suspend fun isExist(history: String): Boolean { 46 | return searchHistoryDao.isExist(history) 47 | } 48 | 49 | suspend fun updateHistory(data: String) { 50 | searchHistoryDao.updateHistory(data, System.currentTimeMillis()) 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/dao/RecentAtUserDao.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.dao 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.Dao 5 | import androidx.room.Delete 6 | import androidx.room.Insert 7 | import androidx.room.Query 8 | import androidx.room.Transaction 9 | import com.example.c001apk.compose.logic.model.RecentAtUser 10 | import kotlinx.coroutines.flow.Flow 11 | 12 | 13 | @Dao 14 | interface RecentAtUserDao { 15 | 16 | @Insert 17 | suspend fun insert(data: RecentAtUser) 18 | 19 | @Insert 20 | suspend fun insertList(list: List) 21 | 22 | @Query("SELECT * FROM RecentAtUser ORDER BY id DESC") 23 | suspend fun loadAllList(): List 24 | 25 | @Query("SELECT * FROM RecentAtUser ORDER BY id DESC") 26 | fun loadAllListLive(): LiveData> 27 | 28 | @Query("SELECT * FROM RecentAtUser ORDER BY id DESC") 29 | fun loadAllListFlow(): Flow> 30 | 31 | @Query("SELECT 1 FROM RecentAtUser WHERE username = :username LIMIT 1") 32 | suspend fun isExist(username: String): Boolean 33 | 34 | @Transaction 35 | @Query("SELECT 1 FROM RecentAtUser WHERE :username LIKE '%' || username || '%' LIMIT 1") 36 | suspend fun isContain(username: String): Boolean 37 | 38 | @Query("DELETE FROM RecentAtUser WHERE username = :username") 39 | suspend fun delete(username: String) 40 | 41 | @Delete 42 | suspend fun delete(data: RecentAtUser) 43 | 44 | @Query("DELETE FROM RecentAtUser") 45 | suspend fun deleteAll() 46 | 47 | @Query("UPDATE RecentAtUser SET id = :newId WHERE username = :username") 48 | suspend fun updateUser(username: String, newId: Long) 49 | 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/dyh/DyhContentScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.dyh 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.platform.LocalContext 6 | import androidx.hilt.navigation.compose.hiltViewModel 7 | import com.example.c001apk.compose.ui.component.CommonScreen 8 | import com.example.c001apk.compose.util.ReportType 9 | import com.example.c001apk.compose.util.makeToast 10 | 11 | /** 12 | * Created by bggRGjQaUbCoE on 2024/6/12 13 | */ 14 | @Composable 15 | fun DyhContentScreen( 16 | id: String, 17 | type: String, 18 | refreshState: Boolean, 19 | resetRefreshState: () -> Unit, 20 | paddingValues: PaddingValues, 21 | onViewUser: (String) -> Unit, 22 | onViewFeed: (String, Boolean) -> Unit, 23 | onOpenLink: (String, String?) -> Unit, 24 | onCopyText: (String?) -> Unit, 25 | onReport: (String, ReportType) -> Unit, 26 | ) { 27 | 28 | val viewModel = 29 | hiltViewModel(key = id + type) { factory -> 30 | factory.create(id, type) 31 | } 32 | 33 | CommonScreen( 34 | viewModel = viewModel, 35 | refreshState = refreshState, 36 | resetRefreshState = resetRefreshState, 37 | paddingValues = paddingValues, 38 | onViewUser = onViewUser, 39 | onViewFeed = onViewFeed, 40 | onOpenLink = onOpenLink, 41 | onCopyText = onCopyText, 42 | onReport = onReport, 43 | ) 44 | 45 | val context = LocalContext.current 46 | viewModel.toastText?.let{ 47 | viewModel.resetToastText() 48 | context.makeToast(it) 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_feed_top.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 13 | 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/coolpic/CoolPicContentScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.coolpic 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.platform.LocalContext 6 | import androidx.hilt.navigation.compose.hiltViewModel 7 | import com.example.c001apk.compose.ui.component.CommonScreen 8 | import com.example.c001apk.compose.util.ReportType 9 | import com.example.c001apk.compose.util.makeToast 10 | 11 | /** 12 | * Created by bggRGjQaUbCoE on 2024/6/12 13 | */ 14 | @Composable 15 | fun CoolPicContentScreen( 16 | title: String, 17 | type: String, 18 | refreshState: Boolean, 19 | resetRefreshState: () -> Unit, 20 | paddingValues: PaddingValues, 21 | onViewUser: (String) -> Unit, 22 | onViewFeed: (String, Boolean) -> Unit, 23 | onOpenLink: (String, String?) -> Unit, 24 | onCopyText: (String?) -> Unit, 25 | onReport: (String, ReportType) -> Unit, 26 | ) { 27 | 28 | val viewModel = 29 | hiltViewModel(key = title + type) { factory -> 30 | factory.create(title, type) 31 | } 32 | 33 | CommonScreen( 34 | viewModel = viewModel, 35 | refreshState = refreshState, 36 | resetRefreshState = resetRefreshState, 37 | paddingValues = paddingValues, 38 | onViewUser = onViewUser, 39 | onViewFeed = onViewFeed, 40 | onOpenLink = onOpenLink, 41 | onCopyText = onCopyText, 42 | onReport = onReport, 43 | ) 44 | 45 | val context = LocalContext.current 46 | viewModel.toastText?.let{ 47 | viewModel.resetToastText() 48 | context.makeToast(it) 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/dao/StringEntityDao.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.dao 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.room.Dao 5 | import androidx.room.Delete 6 | import androidx.room.Insert 7 | import androidx.room.Query 8 | import androidx.room.Transaction 9 | import com.example.c001apk.compose.logic.model.StringEntity 10 | import kotlinx.coroutines.flow.Flow 11 | 12 | 13 | @Dao 14 | interface StringEntityDao { 15 | 16 | @Insert 17 | suspend fun insert(data: StringEntity) 18 | 19 | @Insert 20 | suspend fun insertList(list: List) 21 | 22 | @Query("SELECT * FROM StringEntity ORDER BY id DESC") 23 | suspend fun loadAllList(): List 24 | 25 | @Query("SELECT * FROM StringEntity ORDER BY id DESC") 26 | fun loadAllListLive(): LiveData> 27 | 28 | @Query("SELECT * FROM StringEntity ORDER BY id DESC") 29 | fun loadAllListFlow(): Flow> 30 | 31 | @Query("SELECT 1 FROM StringEntity WHERE data = :data LIMIT 1") 32 | suspend fun isExist(data: String): Boolean 33 | 34 | @Transaction 35 | @Query("SELECT 1 FROM StringEntity WHERE :data LIKE '%' || data || '%' LIMIT 1") 36 | suspend fun isContain(data: String): Boolean 37 | 38 | @Query("DELETE FROM StringEntity WHERE data = :data") 39 | suspend fun delete(data: String) 40 | 41 | @Delete 42 | suspend fun delete(data: StringEntity) 43 | 44 | @Query("DELETE FROM StringEntity") 45 | suspend fun deleteAll() 46 | 47 | @Query("UPDATE StringEntity SET id = :newId WHERE data = :data") 48 | suspend fun updateHistory(data: String, newId: Long) 49 | 50 | @Query("UPDATE StringEntity SET id = :newId , data = :newData WHERE data = :oldData") 51 | suspend fun updateEmoji(oldData: String, newData: String, newId: Long) 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/carousel/CarouselContentScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.carousel 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.platform.LocalContext 6 | import androidx.hilt.navigation.compose.hiltViewModel 7 | import com.example.c001apk.compose.ui.component.CommonScreen 8 | import com.example.c001apk.compose.util.ReportType 9 | import com.example.c001apk.compose.util.makeToast 10 | 11 | /** 12 | * Created by bggRGjQaUbCoE on 2024/6/11 13 | */ 14 | @Composable 15 | fun CarouselContentScreen( 16 | url: String, 17 | title: String, 18 | paddingValues: PaddingValues, 19 | refreshState: Boolean?, 20 | resetRefreshState: () -> Unit, 21 | onViewUser: (String) -> Unit, 22 | onViewFeed: (String, Boolean) -> Unit, 23 | onOpenLink: (String, String?) -> Unit, 24 | onCopyText: (String?) -> Unit, 25 | isHomeFeed: Boolean = false, 26 | onReport: ((String, ReportType) -> Unit)? = null, 27 | ) { 28 | 29 | val viewModel = 30 | hiltViewModel(key = title + url) { factory -> 31 | factory.create(isInit = false, url = url, title = title) 32 | } 33 | 34 | CommonScreen( 35 | viewModel = viewModel, 36 | refreshState = refreshState, 37 | resetRefreshState = resetRefreshState, 38 | paddingValues = paddingValues, 39 | onViewUser = onViewUser, 40 | onViewFeed = onViewFeed, 41 | onOpenLink = onOpenLink, 42 | onCopyText = onCopyText, 43 | isHomeFeed = isHomeFeed, 44 | onReport = onReport, 45 | ) 46 | 47 | val context = LocalContext.current 48 | viewModel.toastText?.let { 49 | viewModel.resetToastText() 50 | context.makeToast(it) 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/repository/RecentEmojiRepo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.repository 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.example.c001apk.compose.di.RecentEmoji 5 | import com.example.c001apk.compose.logic.dao.StringEntityDao 6 | import com.example.c001apk.compose.logic.model.StringEntity 7 | import kotlinx.coroutines.flow.Flow 8 | import javax.inject.Inject 9 | import javax.inject.Singleton 10 | 11 | @Singleton 12 | class RecentEmojiRepo @Inject constructor( 13 | @RecentEmoji 14 | private val recentEmojiDao: StringEntityDao, 15 | ) { 16 | 17 | fun loadAllListLive(): LiveData> { 18 | return recentEmojiDao.loadAllListLive() 19 | } 20 | 21 | fun loadAllListFlow(): Flow> { 22 | return recentEmojiDao.loadAllListFlow() 23 | } 24 | 25 | suspend fun insertEmoji(emoji: StringEntity) { 26 | recentEmojiDao.insert(emoji) 27 | } 28 | 29 | suspend fun insertList(list: List) { 30 | recentEmojiDao.insertList(list) 31 | } 32 | 33 | suspend fun saveEmoji(emoji: String) { 34 | if (!recentEmojiDao.isExist(emoji)) { 35 | recentEmojiDao.insert(StringEntity(emoji)) 36 | } 37 | } 38 | 39 | suspend fun deleteEmoji(emoji: String) { 40 | recentEmojiDao.delete(emoji) 41 | } 42 | 43 | suspend fun deleteEmoji(emoji: StringEntity) { 44 | recentEmojiDao.delete(emoji) 45 | } 46 | 47 | suspend fun deleteAll() { 48 | recentEmojiDao.deleteAll() 49 | } 50 | 51 | suspend fun checkEmoji(emoji: String): Boolean { 52 | return recentEmojiDao.isExist(emoji) 53 | } 54 | 55 | suspend fun updateEmoji(data: String) { 56 | recentEmojiDao.updateHistory(data, System.currentTimeMillis()) 57 | } 58 | 59 | suspend fun updateEmoji(oldData: String, newData: String) { 60 | recentEmojiDao.updateEmoji(oldData, newData, System.currentTimeMillis()) 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/util/TokenDeviceUtils.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.util 2 | 3 | import android.util.Base64 4 | import com.example.c001apk.compose.constant.Constants 5 | import com.example.c001apk.compose.constant.Constants.EMPTY_STRING 6 | import com.example.c001apk.compose.util.Utils.getBase64 7 | import com.example.c001apk.compose.util.Utils.getMD5 8 | import org.mindrot.jbcrypt.BCrypt 9 | import java.nio.charset.Charset 10 | import java.nio.charset.StandardCharsets 11 | import java.util.Random 12 | 13 | 14 | object TokenDeviceUtils { 15 | 16 | fun encode(deviceInfo: String): String { 17 | val charset: Charset = StandardCharsets.UTF_8 18 | val bytes = deviceInfo.toByteArray(charset) 19 | val encodeToString = Base64.encodeToString(bytes, 0) 20 | val replace = StringBuilder(encodeToString).reverse().toString() 21 | return Regex("\\r\\n|\\r|\\n|=").replace(replace, EMPTY_STRING) 22 | } 23 | 24 | fun randHexString(@Suppress("SameParameterValue") n: Int): String { 25 | Random().setSeed(System.currentTimeMillis()) 26 | return (0 until n).joinToString("") { 27 | Random().nextInt(256).toString(16) 28 | }.uppercase() 29 | } 30 | 31 | fun String.getTokenV2(): String { 32 | val timeStamp = (System.currentTimeMillis() / 1000f).toString() 33 | 34 | val base64TimeStamp = timeStamp.getBase64() 35 | val md5TimeStamp = timeStamp.getMD5() 36 | val md5DeviceCode = this.getMD5() 37 | 38 | val token = "${Constants.APP_LABEL}?$md5TimeStamp$$md5DeviceCode&${Constants.APP_ID}" 39 | val base64Token = token.getBase64() 40 | val md5Base64Token = base64Token.getMD5() 41 | val md5Token = token.getMD5() 42 | 43 | val bcryptSalt = "${"$2a$10$$base64TimeStamp/$md5Token".substring(0, 31)}u" 44 | val bcryptResult = BCrypt.hashpw(md5Base64Token, bcryptSalt) 45 | 46 | return "v2${bcryptResult.replaceRange(0, 3, "$2y").getBase64()}" 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /app/src/main/proto/UserPreferences.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_package = "com.example.c001apk.compose"; 4 | option java_multiple_files = true; 5 | 6 | message UserPreferences { 7 | ThemeMode themeMode = 1; 8 | bool materialYou = 2; 9 | bool pureBlack = 3; 10 | float fontScale = 4; 11 | float contentScale = 5; 12 | string szlmId = 6; 13 | int32 imageQuality = 7; 14 | bool imageFilter = 8; 15 | bool openInBrowser = 9; 16 | bool showSquare = 10; 17 | bool recordHistory = 11; 18 | bool showEmoji = 12; 19 | bool checkUpdate = 13; 20 | bool checkCount = 14; 21 | string versionName = 15; 22 | string apiVersion = 16; 23 | string versionCode = 17; 24 | string manufacturer = 18; 25 | string brand = 19; 26 | string model = 20; 27 | string buildNumber = 21; 28 | string sdkInt = 22; 29 | string androidVersion = 23; 30 | string userAgent = 24; 31 | string xAppDevice = 25; 32 | string xAppToken = 26; 33 | bool isLogin = 27; 34 | string userAvatar = 28; 35 | string username = 29; 36 | string level = 30; 37 | string experience = 31; 38 | string nextLevelExperience = 32; 39 | string uid = 33; 40 | string token = 34; 41 | FollowType followType = 35; 42 | string recentIds = 36; 43 | int32 checkCountPeriod = 37; 44 | string installTime = 38; 45 | ThemeType themeType = 39; 46 | string seedColor = 40; 47 | int32 paletteStyle = 41; 48 | } 49 | 50 | enum ThemeType{ 51 | Default = 0; 52 | Red = 1; 53 | Pink = 2; 54 | Purple = 3; 55 | Indigo = 4; 56 | Blue = 5; 57 | LightBlue = 6; 58 | Cyan = 7; 59 | Teal = 8; 60 | Green = 9; 61 | LightGreen = 10; 62 | Lime = 11; 63 | Yellow = 12; 64 | Amber = 13; 65 | Orange = 14; 66 | DeepOrange = 15; 67 | Brown = 16; 68 | BlueGrey = 17; 69 | Sakura = 18; 70 | Custom = 19; 71 | } 72 | 73 | enum FollowType{ 74 | ALL = 0; 75 | USER = 1; 76 | TOPIC = 2; 77 | PRODUCT = 3; 78 | APP = 4; 79 | } 80 | 81 | enum ThemeMode { 82 | FOLLOW_SYSTEM = 0; 83 | ALWAYS_ON = 1; 84 | ALWAYS_OFF = 2; 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/others/CopyTextScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.others 2 | 3 | import androidx.compose.foundation.layout.Box 4 | import androidx.compose.foundation.layout.fillMaxSize 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.rememberScrollState 7 | import androidx.compose.foundation.text.selection.SelectionContainer 8 | import androidx.compose.foundation.verticalScroll 9 | import androidx.compose.material3.MaterialTheme 10 | import androidx.compose.material3.Scaffold 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.unit.dp 16 | import androidx.compose.ui.unit.sp 17 | import com.example.c001apk.compose.util.Utils.richToString 18 | import com.example.c001apk.compose.util.decode 19 | import com.example.c001apk.compose.util.getAllLinkAndText 20 | 21 | /** 22 | * Created by bggRGjQaUbCoE on 2024/6/7 23 | */ 24 | @Composable 25 | fun CopyTextScreen(text: String) { 26 | 27 | Scaffold( 28 | modifier = Modifier.fillMaxSize(), 29 | ) { paddingValues -> 30 | SelectionContainer { 31 | Box(modifier = Modifier.fillMaxSize()) { 32 | Text( 33 | text = text 34 | .decode 35 | .getAllLinkAndText 36 | .replace("\n", "
") 37 | .richToString(), 38 | style = MaterialTheme.typography.titleLarge.copy( 39 | fontSize = 20.sp, 40 | lineHeight = 35.sp 41 | ), 42 | modifier = Modifier 43 | .padding(paddingValues) 44 | .align(Alignment.Center) 45 | .verticalScroll(rememberScrollState()) 46 | .padding(horizontal = 20.dp, vertical = 25.dp) 47 | ) 48 | } 49 | } 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/search/SearchContentViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.search 2 | 3 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 4 | import com.example.c001apk.compose.logic.repository.BlackListRepo 5 | import com.example.c001apk.compose.logic.repository.NetworkRepo 6 | import com.example.c001apk.compose.ui.base.BaseViewModel 7 | import dagger.assisted.Assisted 8 | import dagger.assisted.AssistedFactory 9 | import dagger.assisted.AssistedInject 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/9 14 | */ 15 | @HiltViewModel(assistedFactory = SearchContentViewModel.ViewModelFactory::class) 16 | class SearchContentViewModel @AssistedInject constructor( 17 | @Assisted("type") val type: String, 18 | @Assisted("keyword") val keyword: String, 19 | @Assisted("pageType") val pageType: String?, 20 | @Assisted("pageParam") var pageParam: String?, 21 | networkRepo: NetworkRepo, 22 | blackListRepo: BlackListRepo, 23 | ) : BaseViewModel(networkRepo, blackListRepo) { 24 | 25 | @AssistedFactory 26 | interface ViewModelFactory { 27 | fun create( 28 | @Assisted("type") type: String, 29 | @Assisted("keyword") keyword: String, 30 | @Assisted("pageType") pageType: String?, 31 | @Assisted("pageParam") pageParam: String?, 32 | ): SearchContentViewModel 33 | } 34 | 35 | var feedType: String = "all" 36 | var sort: String = "default" //hot // reply 37 | 38 | var searchFeedType = SearchFeedType.ALL 39 | var sortType = SearchOrderType.DATELINE 40 | 41 | init { 42 | fetchData() 43 | } 44 | 45 | override suspend fun customFetchData() = 46 | networkRepo.getSearch( 47 | type, feedType, sort, keyword, 48 | pageType, pageParam, page, lastItem 49 | ) 50 | 51 | override fun handleLoadMore(response: List): List { 52 | return response.distinctBy { it.entityId } 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/cards/TitleCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.cards 2 | 3 | import androidx.compose.foundation.layout.Row 4 | import androidx.compose.foundation.layout.fillMaxWidth 5 | import androidx.compose.foundation.layout.padding 6 | import androidx.compose.foundation.layout.size 7 | import androidx.compose.material.icons.Icons 8 | import androidx.compose.material.icons.automirrored.filled.ArrowForwardIos 9 | import androidx.compose.material3.Icon 10 | import androidx.compose.material3.MaterialTheme 11 | import androidx.compose.material3.Text 12 | import androidx.compose.runtime.Composable 13 | import androidx.compose.ui.Alignment 14 | import androidx.compose.ui.Modifier 15 | import androidx.compose.ui.draw.clip 16 | import androidx.compose.ui.text.font.FontWeight 17 | import androidx.compose.ui.unit.dp 18 | import androidx.compose.ui.unit.sp 19 | import com.example.c001apk.compose.util.noRippleClickable 20 | 21 | /** 22 | * Created by bggRGjQaUbCoE on 2024/6/6 23 | */ 24 | @Composable 25 | fun TitleCard( 26 | modifier: Modifier = Modifier, 27 | url: String, 28 | title: String, 29 | onOpenLink: (String, String?) -> Unit, 30 | ) { 31 | 32 | Row( 33 | modifier = modifier 34 | .fillMaxWidth() 35 | .clip(MaterialTheme.shapes.medium) 36 | .noRippleClickable(enabled = url.isNotEmpty()) { 37 | onOpenLink(url, title) 38 | } 39 | .padding(horizontal = 10.dp), 40 | verticalAlignment = Alignment.CenterVertically 41 | ) { 42 | Text( 43 | text = title, 44 | fontWeight = FontWeight.Bold, 45 | fontSize = 16.sp, 46 | modifier = Modifier.weight(1f) 47 | ) 48 | 49 | if (url.isNotEmpty()) { 50 | Icon( 51 | imageVector = Icons.AutoMirrored.Filled.ArrowForwardIos, 52 | contentDescription = null, 53 | tint = MaterialTheme.colorScheme.outline, 54 | modifier = Modifier.size(15.dp) 55 | ) 56 | } 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_author.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 12 | 15 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/app/AppContentScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.app 2 | 3 | import androidx.compose.foundation.layout.WindowInsets 4 | import androidx.compose.foundation.layout.WindowInsetsSides 5 | import androidx.compose.foundation.layout.asPaddingValues 6 | import androidx.compose.foundation.layout.navigationBars 7 | import androidx.compose.foundation.layout.only 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.platform.LocalContext 10 | import androidx.hilt.navigation.compose.hiltViewModel 11 | import com.example.c001apk.compose.ui.component.CommonScreen 12 | import com.example.c001apk.compose.util.ReportType 13 | import com.example.c001apk.compose.util.makeToast 14 | 15 | /** 16 | * Created by bggRGjQaUbCoE on 2024/6/10 17 | */ 18 | @Composable 19 | fun AppContentScreen( 20 | refreshState: Boolean, 21 | resetRefreshState: () -> Unit, 22 | id: String, 23 | appCommentSort: String, 24 | appCommentTitle: String, 25 | onViewUser: (String) -> Unit, 26 | onViewFeed: (String, Boolean) -> Unit, 27 | onOpenLink: (String, String?) -> Unit, 28 | onCopyText: (String?) -> Unit, 29 | onReport: (String, ReportType) -> Unit, 30 | isScrollingUp: ((Boolean) -> Unit)? = null, 31 | ) { 32 | 33 | val viewModel = 34 | hiltViewModel(key = id + appCommentSort) { factory -> 35 | factory.create( 36 | url = "/page?url=/feed/apkCommentList?id=$id$appCommentSort", 37 | appCommentTitle = appCommentTitle 38 | ) 39 | } 40 | 41 | val windowInsets = 42 | WindowInsets.navigationBars.only(WindowInsetsSides.Start + WindowInsetsSides.Bottom) 43 | 44 | CommonScreen( 45 | viewModel = viewModel, 46 | refreshState = refreshState, 47 | resetRefreshState = resetRefreshState, 48 | paddingValues = windowInsets.asPaddingValues(), 49 | onViewUser = onViewUser, 50 | onViewFeed = onViewFeed, 51 | onOpenLink = onOpenLink, 52 | onCopyText = onCopyText, 53 | onReport = onReport, 54 | isScrollingUp = isScrollingUp, 55 | ) 56 | 57 | val context = LocalContext.current 58 | viewModel.toastText?.let { 59 | viewModel.resetToastText() 60 | context.makeToast(it) 61 | } 62 | 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/util/AddCookiesInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.util 2 | 3 | import com.example.c001apk.compose.constant.Constants.APP_ID 4 | import com.example.c001apk.compose.constant.Constants.CHANNEL 5 | import com.example.c001apk.compose.constant.Constants.DARK_MODE 6 | import com.example.c001apk.compose.constant.Constants.LOCALE 7 | import com.example.c001apk.compose.constant.Constants.MODE 8 | import com.example.c001apk.compose.constant.Constants.REQUEST_WITH 9 | import com.example.c001apk.compose.util.CookieUtil.SESSID 10 | import com.example.c001apk.compose.util.TokenDeviceUtils.getTokenV2 11 | import okhttp3.Interceptor 12 | import okhttp3.Request 13 | import okhttp3.Response 14 | import java.io.IOException 15 | 16 | /** 17 | * Created by bggRGjQaUbCoE on 2024/6/3 18 | */ 19 | object AddCookiesInterceptor : Interceptor { 20 | 21 | @Throws(IOException::class) 22 | override fun intercept(chain: Interceptor.Chain): Response { 23 | val builder: Request.Builder = chain.request().newBuilder() 24 | val deviceCode = CookieUtil.xAppDevice 25 | val token = deviceCode.getTokenV2() 26 | builder.apply { 27 | addHeader("User-Agent", CookieUtil.userAgent) 28 | addHeader("X-Requested-With", REQUEST_WITH) 29 | addHeader("X-Sdk-Int", CookieUtil.sdkInt) 30 | addHeader("X-Sdk-Locale", LOCALE) 31 | addHeader("X-App-Id", APP_ID) 32 | addHeader("X-App-Token", token) 33 | addHeader("X-App-Version", CookieUtil.versionName) 34 | addHeader("X-App-Code", CookieUtil.versionCode) 35 | addHeader("X-Api-Version", CookieUtil.apiVersion) 36 | addHeader("X-App-Device", deviceCode) 37 | addHeader("X-Dark-Mode", DARK_MODE) 38 | addHeader("X-App-Channel", CHANNEL) 39 | addHeader("X-App-Mode", MODE) 40 | addHeader("X-App-Supported", CookieUtil.versionCode) 41 | addHeader("Content-Type", "application/x-www-form-urlencoded") 42 | if (CookieUtil.isLogin) 43 | addHeader( 44 | "Cookie", 45 | "uid=${CookieUtil.uid}; username=${CookieUtil.username}; token=${CookieUtil.token}" 46 | ) 47 | else addHeader("Cookie", SESSID) 48 | } 49 | return chain.proceed(builder.build()) 50 | } 51 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/history/HistoryViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.history 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import com.example.c001apk.compose.logic.repository.BlackListRepo 6 | import com.example.c001apk.compose.logic.repository.HistoryFavoriteRepo 7 | import dagger.assisted.Assisted 8 | import dagger.assisted.AssistedFactory 9 | import dagger.assisted.AssistedInject 10 | import dagger.hilt.android.lifecycle.HiltViewModel 11 | import kotlinx.coroutines.Dispatchers 12 | import kotlinx.coroutines.launch 13 | 14 | /** 15 | * Created by bggRGjQaUbCoE on 2024/6/17 16 | */ 17 | @HiltViewModel(assistedFactory = HistoryViewModel.ViewModelFactory::class) 18 | class HistoryViewModel @AssistedInject constructor( 19 | @Assisted val type: HistoryType = HistoryType.HISTORY, 20 | private val blackListRepo: BlackListRepo, 21 | private val historyFavoriteRepo: HistoryFavoriteRepo 22 | ) : ViewModel() { 23 | 24 | @AssistedFactory 25 | interface ViewModelFactory { 26 | fun create(type: HistoryType): HistoryViewModel 27 | } 28 | 29 | val dataList = when (type) { 30 | HistoryType.FAV -> historyFavoriteRepo.loadAllFavoriteListFlow() 31 | HistoryType.HISTORY -> historyFavoriteRepo.loadAllHistoryListFlow() 32 | } 33 | 34 | fun blockUser(uid: String) { 35 | viewModelScope.launch(Dispatchers.IO) { 36 | if (!blackListRepo.checkUid(uid)) { 37 | blackListRepo.saveUid(uid) 38 | } 39 | when (type) { 40 | HistoryType.FAV -> historyFavoriteRepo.deleteFavByUid(uid) 41 | HistoryType.HISTORY -> historyFavoriteRepo.deleteHistoryByUid(uid) 42 | } 43 | } 44 | } 45 | 46 | fun delete(id: String) { 47 | viewModelScope.launch(Dispatchers.IO) { 48 | when (type) { 49 | HistoryType.FAV -> historyFavoriteRepo.deleteFavorite(id) 50 | HistoryType.HISTORY -> historyFavoriteRepo.deleteHistory(id) 51 | } 52 | } 53 | } 54 | 55 | fun clearAll() { 56 | viewModelScope.launch(Dispatchers.IO) { 57 | when (type) { 58 | HistoryType.FAV -> historyFavoriteRepo.deleteAllFavorite() 59 | HistoryType.HISTORY -> historyFavoriteRepo.deleteAllHistory() 60 | } 61 | } 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/settings/BasicListItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.settings 2 | 3 | import androidx.compose.foundation.Image 4 | import androidx.compose.foundation.clickable 5 | import androidx.compose.foundation.layout.size 6 | import androidx.compose.material3.Icon 7 | import androidx.compose.material3.ListItem 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.material3.Text 10 | import androidx.compose.runtime.Composable 11 | import androidx.compose.ui.Modifier 12 | import androidx.compose.ui.draw.clip 13 | import androidx.compose.ui.graphics.painter.Painter 14 | import androidx.compose.ui.graphics.vector.ImageVector 15 | import androidx.compose.ui.unit.dp 16 | 17 | @Composable 18 | fun BasicListItem( 19 | modifier: Modifier = Modifier, 20 | headlineText: String? = null, 21 | supportingText: String? = null, 22 | leadingImageVector: ImageVector? = null, 23 | leadingPainter: Painter? = null, 24 | leadingText: String? = null, 25 | trailingContent: @Composable () -> Unit = {}, 26 | onClick: (() -> Unit)? = null, 27 | ) { 28 | ListItem( 29 | modifier = onClick?.let { 30 | modifier.clickable( 31 | onClick = onClick 32 | ) 33 | } ?: modifier, 34 | headlineContent = { 35 | if (headlineText != null) { 36 | Text(headlineText) 37 | } 38 | }, 39 | supportingContent = { 40 | if (supportingText != null) { 41 | Text(supportingText) 42 | } 43 | }, 44 | leadingContent = { 45 | if (leadingText != null) { 46 | Text( 47 | text = leadingText, 48 | color = MaterialTheme.colorScheme.primary, 49 | style = MaterialTheme.typography.titleSmall 50 | ) 51 | } else if (leadingImageVector != null) { 52 | Icon(imageVector = leadingImageVector, contentDescription = null) 53 | } else if (leadingPainter != null) { 54 | Image( 55 | painter = leadingPainter, contentDescription = null, modifier = Modifier 56 | .clip(MaterialTheme.shapes.medium) 57 | .size(24.dp) 58 | ) 59 | } 60 | }, 61 | trailingContent = trailingContent 62 | ) 63 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/IconText.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component 2 | 3 | import androidx.compose.foundation.text.InlineTextContent 4 | import androidx.compose.foundation.text.appendInlineContent 5 | import androidx.compose.material3.Icon 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.ui.Modifier 10 | import androidx.compose.ui.graphics.vector.ImageVector 11 | import androidx.compose.ui.text.Placeholder 12 | import androidx.compose.ui.text.PlaceholderVerticalAlign 13 | import androidx.compose.ui.text.buildAnnotatedString 14 | import androidx.compose.ui.text.style.TextOverflow 15 | import androidx.compose.ui.unit.sp 16 | import com.example.c001apk.compose.util.noRippleClickable 17 | 18 | /** 19 | * Created by bggRGjQaUbCoE on 2024/6/9 20 | */ 21 | @Composable 22 | fun IconText( 23 | modifier: Modifier = Modifier, 24 | imageVector: ImageVector, 25 | title: String, 26 | textSize: Float = 14f, 27 | onClick: (() -> Unit)? = null, 28 | isLike: Boolean = false, 29 | ) { 30 | 31 | val color = if (isLike) MaterialTheme.colorScheme.primary 32 | else MaterialTheme.colorScheme.outline 33 | 34 | val id = "0" 35 | val text1 = buildAnnotatedString { 36 | if (title.isNotEmpty()) appendInlineContent(id, "[icon]") 37 | append(title) 38 | } 39 | 40 | val inlineContent = if (title.isNotEmpty()) mapOf( 41 | Pair( 42 | id, 43 | InlineTextContent( 44 | Placeholder( 45 | width = textSize.sp, 46 | height = textSize.sp, 47 | placeholderVerticalAlign = PlaceholderVerticalAlign.TextCenter 48 | ) 49 | ) { 50 | Icon(imageVector, null, tint = color) 51 | } 52 | ) 53 | ) else mapOf() 54 | 55 | Text( 56 | inlineContent = inlineContent, 57 | text = text1, 58 | lineHeight = textSize.sp, 59 | fontSize = textSize.sp, 60 | color = color, 61 | maxLines = 1, 62 | overflow = TextOverflow.Ellipsis, 63 | modifier = run { 64 | val tmp = if (onClick == null) modifier 65 | else modifier 66 | .noRippleClickable { 67 | onClick() 68 | } 69 | tmp 70 | } 71 | ) 72 | 73 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/NineImageView.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component 2 | 3 | import androidx.compose.material3.MaterialTheme 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.graphics.toArgb 7 | import androidx.compose.ui.viewinterop.AndroidView 8 | import com.example.c001apk.compose.constant.Constants.SUFFIX_THUMBNAIL 9 | import com.example.c001apk.compose.logic.providable.LocalUserPreferences 10 | import com.example.c001apk.compose.util.ImageShowUtil.getImageLp 11 | import com.example.c001apk.compose.view.NineGridImageView 12 | 13 | /** 14 | * Created by bggRGjQaUbCoE on 2024/6/5 15 | */ 16 | @Composable 17 | fun NineImageView( 18 | modifier: Modifier = Modifier, 19 | pic: String?, 20 | picArr: List?, 21 | feedType: String?, 22 | isSingle: Boolean = false 23 | ) { 24 | val prefs = LocalUserPreferences.current 25 | 26 | val primaryContainer = MaterialTheme.colorScheme.primaryContainer.toArgb() 27 | val onPrimaryContainer = MaterialTheme.colorScheme.onPrimaryContainer.toArgb() 28 | 29 | AndroidView( 30 | modifier = modifier, 31 | factory = { 32 | NineGridImageView(it).apply { 33 | this.colorPrimaryContainer = primaryContainer 34 | this.colorOnPrimaryContainer = onPrimaryContainer 35 | this.isSingle = isSingle 36 | this.userAgent = prefs.userAgent 37 | } 38 | }, 39 | update = { imageView -> 40 | if (!picArr.isNullOrEmpty()) { 41 | if (picArr.size == 1 || feedType in listOf("feedArticle", "trade")) { 42 | val imageLp = getImageLp(pic ?: picArr[0]) 43 | imageView.imgWidth = imageLp.first 44 | imageView.imgHeight = imageLp.second 45 | } 46 | imageView.apply { 47 | val urlList: MutableList = ArrayList() 48 | if (feedType in listOf("feedArticle", "trade") && imgWidth > imgHeight) 49 | if (!pic.isNullOrEmpty()) urlList.add("$pic$SUFFIX_THUMBNAIL") 50 | else urlList.add("${picArr[0]}$SUFFIX_THUMBNAIL") 51 | else 52 | urlList.addAll(picArr.map { "$it$SUFFIX_THUMBNAIL" }) 53 | setUrlList(urlList) 54 | } 55 | } 56 | } 57 | ) 58 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/cards/IconMiniGridCard.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.cards 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.foundation.layout.Column 5 | import androidx.compose.foundation.layout.Row 6 | import androidx.compose.foundation.layout.fillMaxWidth 7 | import androidx.compose.foundation.layout.padding 8 | import androidx.compose.material3.MaterialTheme 9 | import androidx.compose.runtime.Composable 10 | import androidx.compose.ui.Modifier 11 | import androidx.compose.ui.draw.clip 12 | import androidx.compose.ui.unit.dp 13 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 14 | import com.example.c001apk.compose.ui.theme.cardBg 15 | 16 | /** 17 | * Created by bggRGjQaUbCoE on 2024/6/7 18 | */ 19 | @Composable 20 | fun IconMiniGridCard( 21 | modifier: Modifier = Modifier, 22 | data: HomeFeedResponse.Data, 23 | onOpenLink: (String, String?) -> Unit 24 | ) { 25 | 26 | 27 | Column( 28 | modifier = modifier 29 | .fillMaxWidth() 30 | .clip(MaterialTheme.shapes.medium) 31 | .background(cardBg()) 32 | .padding(vertical = 5.dp) 33 | ) { 34 | 35 | if (!data.title.isNullOrEmpty()) { 36 | TitleCard( 37 | modifier = Modifier.padding(bottom = 5.dp), 38 | url = data.url.orEmpty(), 39 | title = data.title, 40 | onOpenLink = onOpenLink, 41 | ) 42 | } 43 | 44 | data.entities?.let { 45 | val columnCount = it.size / 2 46 | (0 until columnCount).forEach { column -> 47 | Row( 48 | modifier = Modifier.fillMaxWidth() 49 | ) { 50 | (0..1).forEach { row -> 51 | IconMiniScrollCardItem( 52 | modifier = Modifier.weight(1f), 53 | isFeedContent = true, 54 | isGridCard = true, 55 | logoUrl = it.getOrNull(column * 2 + row)?.logo.orEmpty(), 56 | linkUrl = it.getOrNull(column * 2 + row)?.url.orEmpty(), 57 | titleText = it.getOrNull(column * 2 + row)?.title.orEmpty(), 58 | onOpenLink = onOpenLink 59 | ) 60 | } 61 | } 62 | } 63 | } 64 | 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/settings/DropdownListItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.settings 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.material3.DropdownMenu 5 | import androidx.compose.material3.DropdownMenuItem 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.runtime.getValue 10 | import androidx.compose.runtime.mutableStateOf 11 | import androidx.compose.runtime.remember 12 | import androidx.compose.runtime.setValue 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.graphics.vector.ImageVector 16 | import com.example.c001apk.compose.constant.Constants.EMPTY_STRING 17 | 18 | /** 19 | * Used for selections 20 | * If label is null, then value will be displayed on the screen 21 | */ 22 | data class SelectionItem(val label: String, val value: T) 23 | 24 | @Composable 25 | fun DropdownListItem( 26 | value: T?, 27 | leadingImageVector: ImageVector? = null, 28 | headlineText: String, 29 | selections: List>, 30 | onValueChanged: (index: Int, value: T) -> Unit, 31 | ) { 32 | var dropdownMenuExpanded by remember { mutableStateOf(false) } 33 | BasicListItem( 34 | headlineText = headlineText, 35 | supportingText = selections.find { it.value == value }?.label ?: EMPTY_STRING, 36 | onClick = { dropdownMenuExpanded = true }, 37 | leadingImageVector = leadingImageVector, 38 | trailingContent = { 39 | DropdownMenu( 40 | expanded = dropdownMenuExpanded, 41 | onDismissRequest = { dropdownMenuExpanded = false }, 42 | ) { 43 | selections.forEachIndexed { index, selection -> 44 | DropdownMenuItem( 45 | modifier = Modifier.background( 46 | if (selection.value == value) MaterialTheme.colorScheme.surfaceVariant 47 | else Color.Transparent 48 | ), 49 | text = { Text(selection.label) }, 50 | onClick = { 51 | dropdownMenuExpanded = false 52 | onValueChanged(index, selection.value) 53 | } 54 | ) 55 | } 56 | } 57 | }, 58 | ) 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/view/circleindicator/Config.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.view.circleindicator 2 | 3 | import android.annotation.SuppressLint 4 | import android.view.Gravity 5 | import android.widget.LinearLayout 6 | import androidx.annotation.AnimatorRes 7 | import androidx.annotation.DrawableRes 8 | import com.example.c001apk.compose.R 9 | 10 | class Config internal constructor() { 11 | var width = -1 12 | var height = -1 13 | var margin = -1 14 | 15 | @SuppressLint("ResourceType") 16 | @AnimatorRes 17 | var animatorResId = R.anim.scale_with_alpha 18 | 19 | @AnimatorRes 20 | var animatorReverseResId = 0 21 | 22 | @DrawableRes 23 | var backgroundResId = R.drawable.white_radius 24 | 25 | @DrawableRes 26 | var unselectedBackgroundId = 0 27 | var orientation = LinearLayout.HORIZONTAL 28 | var gravity = Gravity.CENTER 29 | 30 | class Builder { 31 | private val mConfig: Config = Config() 32 | 33 | fun width(width: Int): Builder { 34 | mConfig.width = width 35 | return this 36 | } 37 | 38 | fun height(height: Int): Builder { 39 | mConfig.height = height 40 | return this 41 | } 42 | 43 | fun margin(margin: Int): Builder { 44 | mConfig.margin = margin 45 | return this 46 | } 47 | 48 | fun animator(@AnimatorRes animatorResId: Int): Builder { 49 | mConfig.animatorResId = animatorResId 50 | return this 51 | } 52 | 53 | fun animatorReverse(@AnimatorRes animatorReverseResId: Int): Builder { 54 | mConfig.animatorReverseResId = animatorReverseResId 55 | return this 56 | } 57 | 58 | fun drawable(@DrawableRes backgroundResId: Int): Builder { 59 | mConfig.backgroundResId = backgroundResId 60 | return this 61 | } 62 | 63 | fun drawableUnselected(@DrawableRes unselectedBackgroundId: Int): Builder { 64 | mConfig.unselectedBackgroundId = unselectedBackgroundId 65 | return this 66 | } 67 | 68 | fun orientation(orientation: Int): Builder { 69 | mConfig.orientation = orientation 70 | return this 71 | } 72 | 73 | fun gravity(gravity: Int): Builder { 74 | mConfig.gravity = gravity 75 | return this 76 | } 77 | 78 | fun build(): Config { 79 | return mConfig 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/settings/StateDropdownListItem.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component.settings 2 | 3 | import androidx.compose.foundation.background 4 | import androidx.compose.material3.DropdownMenu 5 | import androidx.compose.material3.DropdownMenuItem 6 | import androidx.compose.material3.MaterialTheme 7 | import androidx.compose.material3.Text 8 | import androidx.compose.runtime.Composable 9 | import androidx.compose.runtime.getValue 10 | import androidx.compose.runtime.mutableStateOf 11 | import androidx.compose.runtime.remember 12 | import androidx.compose.runtime.setValue 13 | import androidx.compose.ui.Modifier 14 | import androidx.compose.ui.graphics.Color 15 | import androidx.compose.ui.graphics.vector.ImageVector 16 | import com.example.c001apk.compose.constant.Constants.EMPTY_STRING 17 | 18 | /** 19 | * Used for selections 20 | * If label is null, then value will be displayed on the screen 21 | */ 22 | @Composable 23 | fun StateDropdownListItem( 24 | isEnable: Boolean = true, 25 | value: T?, 26 | leadingImageVector: ImageVector? = null, 27 | headlineText: String, 28 | selections: List>, 29 | onValueChanged: (index: Int, value: T) -> Unit, 30 | ) { 31 | var dropdownMenuExpanded by remember { mutableStateOf(false) } 32 | StateBasicListItem( 33 | isEnable = isEnable, 34 | headlineText = headlineText, 35 | supportingText = selections.find { it.value == value }?.label ?: EMPTY_STRING, 36 | onClick = { dropdownMenuExpanded = true }, 37 | leadingImageVector = leadingImageVector, 38 | trailingContent = { 39 | DropdownMenu( 40 | expanded = dropdownMenuExpanded, 41 | onDismissRequest = { dropdownMenuExpanded = false }, 42 | ) { 43 | selections.forEachIndexed { index, selection -> 44 | DropdownMenuItem( 45 | modifier = Modifier.background( 46 | if (selection.value == value) MaterialTheme.colorScheme.surfaceVariant 47 | else Color.Transparent 48 | ), 49 | text = { Text(selection.label) }, 50 | onClick = { 51 | dropdownMenuExpanded = false 52 | onValueChanged(index, selection.value) 53 | } 54 | ) 55 | } 56 | } 57 | }, 58 | ) 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/base/PrefsViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.base 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.viewModelScope 5 | import com.example.c001apk.compose.constant.Constants 6 | import com.example.c001apk.compose.logic.repository.UserPreferencesRepository 7 | import com.example.c001apk.compose.util.CookieUtil.szlmId 8 | import com.example.c001apk.compose.util.CookieUtil.versionCode 9 | import com.example.c001apk.compose.util.CookieUtil.versionName 10 | import com.example.c001apk.compose.util.TokenDeviceUtils.encode 11 | import com.example.c001apk.compose.util.TokenDeviceUtils.randHexString 12 | import com.example.c001apk.compose.util.Utils.randomAndroidVersionRelease 13 | import com.example.c001apk.compose.util.Utils.randomBrand 14 | import com.example.c001apk.compose.util.Utils.randomDeviceModel 15 | import com.example.c001apk.compose.util.Utils.randomMacAddress 16 | import com.example.c001apk.compose.util.Utils.randomManufacturer 17 | import com.example.c001apk.compose.util.Utils.randomSdkInt 18 | import kotlinx.coroutines.launch 19 | 20 | /** 21 | * Created by bggRGjQaUbCoE on 2024/6/15 22 | */ 23 | open class PrefsViewModel( 24 | private val userPreferencesRepository: UserPreferencesRepository 25 | ) : ViewModel() { 26 | 27 | fun regenerateParams() { 28 | viewModelScope.launch { 29 | val manufacturer = randomManufacturer() 30 | val brand = randomBrand() 31 | val model = randomDeviceModel() 32 | val buildNumber = randHexString(16) 33 | val sdkInt = randomSdkInt() 34 | val androidVersion = randomAndroidVersionRelease() 35 | val mac = randomMacAddress() 36 | val userAgent = 37 | "Dalvik/2.1.0 (Linux; U; Android $androidVersion; $model $buildNumber) (#Build; $brand; $model; $buildNumber; $androidVersion) +CoolMarket/$versionName-$versionCode-${Constants.MODE}" 38 | val xAppDevice = 39 | encode("$szlmId; ; ; $mac; $manufacturer; $brand; $model; $buildNumber; null") 40 | 41 | userPreferencesRepository.apply { 42 | setManufacturer(manufacturer) 43 | setBrand(brand) 44 | setModel(model) 45 | setBuildNumber(buildNumber) 46 | setSdkInt(sdkInt) 47 | setAndroidVersion(androidVersion) 48 | setUserAgent(userAgent) 49 | setXAppDevice(xAppDevice) 50 | } 51 | 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/view/BadgedImageView.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.view 2 | 3 | import android.content.Context 4 | import android.graphics.Canvas 5 | import android.graphics.Color 6 | import android.graphics.Rect 7 | import android.view.Gravity 8 | import com.example.c001apk.compose.util.dp 9 | 10 | 11 | /* 12 | Licensed under the Apache License, Version 2.0 (the "License"); 13 | you may not use this file except in compliance with the License. 14 | You may obtain a copy of the License at 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | Unless required by applicable law or agreed to in writing, software 19 | distributed under the License is distributed on an "AS IS" BASIS, 20 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 21 | See the License for the specific language governing permissions and 22 | limitations under the License. 23 | */ 24 | 25 | // mod from https://github.com/klinker24/Android-BadgedImageView 26 | class BadgedImageView( 27 | context: Context, 28 | ) : RoundedImageView(context) { 29 | private var badgeBoundsSet = false 30 | private var badge: BadgeDrawable? = null 31 | private var badgeGravity: Int = Gravity.END or Gravity.BOTTOM 32 | private var badgePadding: Int = 4.dp 33 | var colorPrimaryContainer: Int = Color.BLACK 34 | var colorOnPrimaryContainer: Int = Color.WHITE 35 | 36 | fun setBadge(text: String) { 37 | badge = BadgeDrawable(text, colorPrimaryContainer, colorOnPrimaryContainer) 38 | badgeBoundsSet = false 39 | invalidate() 40 | } 41 | 42 | override fun draw(canvas: Canvas) { 43 | super.draw(canvas) 44 | if (badge != null) { 45 | if (!badgeBoundsSet) { 46 | layoutBadge() 47 | } 48 | badge?.draw(canvas) 49 | } 50 | } 51 | 52 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { 53 | super.onSizeChanged(w, h, oldw, oldh) 54 | if (badge != null) { 55 | layoutBadge() 56 | } 57 | } 58 | 59 | private fun layoutBadge() { 60 | badge?.let { badge -> 61 | val badgeBounds = badge.getBounds() 62 | Gravity.apply( 63 | badgeGravity, 64 | badge.intrinsicWidth, 65 | badge.intrinsicHeight, 66 | Rect(0, 0, width, height), 67 | badgePadding, 68 | badgePadding, 69 | badgeBounds 70 | ) 71 | badge.bounds = badgeBounds 72 | badgeBoundsSet = true 73 | } 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/home/feed/HomeFeedViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.home.feed 2 | 3 | import androidx.lifecycle.viewModelScope 4 | import com.example.c001apk.compose.logic.model.HomeFeedResponse 5 | import com.example.c001apk.compose.logic.repository.BlackListRepo 6 | import com.example.c001apk.compose.logic.repository.NetworkRepo 7 | import com.example.c001apk.compose.logic.repository.UserPreferencesRepository 8 | import com.example.c001apk.compose.ui.base.BaseViewModel 9 | import com.example.c001apk.compose.ui.home.TabType 10 | import dagger.assisted.Assisted 11 | import dagger.assisted.AssistedFactory 12 | import dagger.assisted.AssistedInject 13 | import dagger.hilt.android.lifecycle.HiltViewModel 14 | import kotlinx.coroutines.launch 15 | 16 | /** 17 | * Created by bggRGjQaUbCoE on 2024/6/3 18 | */ 19 | @HiltViewModel(assistedFactory = HomeFeedViewModel.ViewModelFactory::class) 20 | class HomeFeedViewModel @AssistedInject constructor( 21 | @Assisted val type: TabType = TabType.FEED, 22 | @Assisted("dataListUrl") var dataListUrl: String, 23 | @Assisted("dataListTitle") var dataListTitle: String, 24 | @Assisted("installTime") var installTime: String, 25 | networkRepo: NetworkRepo, 26 | blackListRepo: BlackListRepo, 27 | private val userPreferencesRepository: UserPreferencesRepository, 28 | ) : BaseViewModel(networkRepo, blackListRepo) { 29 | 30 | @AssistedFactory 31 | interface ViewModelFactory { 32 | fun create( 33 | type: TabType, 34 | @Assisted("dataListUrl") dataListUrl: String, 35 | @Assisted("dataListTitle") dataListTitle: String, 36 | @Assisted("installTime") installTime: String, 37 | ): HomeFeedViewModel 38 | } 39 | 40 | init { 41 | if (installTime.isEmpty()) { 42 | installTime = System.currentTimeMillis().toString() 43 | setInstallTime() 44 | } 45 | fetchData() 46 | } 47 | 48 | override suspend fun customFetchData() = when (type) { 49 | TabType.FOLLOW, TabType.HOT, TabType.COOLPIC -> 50 | networkRepo.getDataList(dataListUrl, dataListTitle, null, lastItem, page) 51 | 52 | TabType.FEED -> networkRepo.getHomeFeed(page, firstLaunch, installTime, null, null) 53 | 54 | else -> throw IllegalArgumentException("invalid type: ${type.name}") 55 | } 56 | 57 | private fun setInstallTime() { 58 | viewModelScope.launch { 59 | userPreferencesRepository.setInstallTime(installTime) 60 | } 61 | } 62 | 63 | override fun handleLoadMore(response: List): List { 64 | return response.distinctBy { it.entityId } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/component/CoilLoader.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.component 2 | 3 | import android.os.Build 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.ui.Modifier 6 | import androidx.compose.ui.graphics.Color 7 | import androidx.compose.ui.graphics.toArgb 8 | import androidx.compose.ui.layout.ContentScale 9 | import androidx.compose.ui.platform.LocalContext 10 | import coil.compose.AsyncImage 11 | import coil.decode.GifDecoder 12 | import coil.decode.ImageDecoderDecoder 13 | import coil.request.CachePolicy 14 | import coil.request.ImageRequest 15 | import com.example.c001apk.compose.constant.Constants.SUFFIX_GIF 16 | import com.example.c001apk.compose.logic.providable.LocalUserPreferences 17 | import com.example.c001apk.compose.util.CookieUtil 18 | import com.example.c001apk.compose.util.http2https 19 | import jp.wasabeef.transformers.coil.ColorFilterTransformation 20 | 21 | /** 22 | * Created by bggRGjQaUbCoE on 2024/6/11 23 | */ 24 | @Composable 25 | fun CoilLoader( 26 | modifier: Modifier = Modifier, 27 | url: String?, 28 | colorFilter: Long? = null, 29 | ) { 30 | val prefs = LocalUserPreferences.current 31 | url?.let { 32 | val context = LocalContext.current 33 | val imageUrl = it.http2https 34 | AsyncImage( 35 | model = ImageRequest.Builder(context) 36 | .memoryCachePolicy(CachePolicy.ENABLED) 37 | .diskCachePolicy(CachePolicy.ENABLED) 38 | .memoryCacheKey(imageUrl) 39 | .diskCacheKey(imageUrl) 40 | .data(imageUrl) 41 | .addHeader("User-Agent", prefs.userAgent) 42 | .apply { 43 | if (it.endsWith(SUFFIX_GIF)) { 44 | decoderFactory( 45 | if (Build.VERSION.SDK_INT >= 28) { 46 | ImageDecoderDecoder.Factory() 47 | } else { 48 | GifDecoder.Factory() 49 | } 50 | ) 51 | } 52 | colorFilter?.let { 53 | transformations(ColorFilterTransformation(Color(colorFilter).toArgb())) 54 | } 55 | if (!it.endsWith(SUFFIX_GIF) && colorFilter == null && prefs.isDarkMode() && CookieUtil.imageFilter) { 56 | transformations(ColorFilterTransformation(Color(0x2D000000).toArgb())) 57 | } 58 | } 59 | .crossfade(true) 60 | .build(), 61 | contentDescription = null, 62 | contentScale = ContentScale.Crop, 63 | modifier = modifier, 64 | ) 65 | } 66 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/feed/reply/emoji/EmojiGridAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.feed.reply.emoji 2 | 3 | import android.annotation.SuppressLint 4 | import android.os.Build.VERSION.SDK_INT 5 | import android.view.LayoutInflater 6 | import android.view.MotionEvent 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.BaseAdapter 10 | import android.widget.ImageView 11 | import androidx.appcompat.content.res.AppCompatResources 12 | import com.example.c001apk.compose.R 13 | import com.example.c001apk.compose.util.dp 14 | 15 | 16 | class EmojiGridAdapter( 17 | private val emojiList: List>, 18 | private val onClickEmoji: (String) -> Unit, 19 | private val onCountStart: () -> Unit, 20 | private val onCountStop: () -> Unit 21 | ) : BaseAdapter() { 22 | 23 | override fun getCount() = 28 24 | 25 | override fun getItem(position: Int): Any { 26 | return 0 27 | } 28 | 29 | override fun getItemId(position: Int): Long { 30 | return 0 31 | } 32 | 33 | @SuppressLint("ViewHolder", "ClickableViewAccessibility") 34 | override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { 35 | val emoji = emojiList.getOrNull(position) 36 | return if (emoji != null || position == 27) { 37 | val view = 38 | LayoutInflater.from(parent.context).inflate(R.layout.item_emoji, parent, false) 39 | val imageView: ImageView = view.findViewById(R.id.imageView) 40 | 41 | imageView.setImageResource(emoji?.second ?: R.drawable.outline_backspace_24) 42 | emoji?.first?.let { 43 | view.background = 44 | AppCompatResources.getDrawable(parent.context, R.drawable.selector_emoji) 45 | if (SDK_INT >= 26) 46 | view.tooltipText = it.substring(1, it.lastIndex) 47 | } 48 | view.setOnClickListener { 49 | onClickEmoji(emoji?.first ?: "[c001apk]") 50 | } 51 | if (position == 27) { 52 | if (SDK_INT >= 26) 53 | view.tooltipText = null 54 | view.setOnLongClickListener { 55 | onCountStart() 56 | false 57 | } 58 | view.setOnTouchListener { _, event -> 59 | if (event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL) { 60 | onCountStop() 61 | } 62 | false 63 | } 64 | } 65 | view 66 | } else View(parent.context).apply { 67 | layoutParams = ViewGroup.LayoutParams(48.dp, 48.dp) 68 | isEnabled = false 69 | } 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/ui/topic/TopicContentScreen.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.ui.topic 2 | 3 | import androidx.compose.foundation.layout.PaddingValues 4 | import androidx.compose.runtime.Composable 5 | import androidx.compose.runtime.LaunchedEffect 6 | import androidx.compose.ui.platform.LocalContext 7 | import androidx.hilt.navigation.compose.hiltViewModel 8 | import com.example.c001apk.compose.ui.component.CommonScreen 9 | import com.example.c001apk.compose.util.ReportType 10 | import com.example.c001apk.compose.util.makeToast 11 | 12 | /** 13 | * Created by bggRGjQaUbCoE on 2024/6/9 14 | */ 15 | @Composable 16 | fun TopicContentScreen( 17 | refreshState: Boolean, 18 | resetRefreshState: () -> Unit, 19 | entityType: String, 20 | id: String?, 21 | url: String, 22 | title: String, 23 | sortType: ProductSortType, 24 | paddingValues: PaddingValues, 25 | onViewUser: (String) -> Unit, 26 | onViewFeed: (String, Boolean) -> Unit, 27 | onOpenLink: (String, String?) -> Unit, 28 | onCopyText: (String?) -> Unit, 29 | onReport: (String, ReportType) -> Unit, 30 | isScrollingUp: ((Boolean) -> Unit)? = null, 31 | ) { 32 | 33 | val viewModel = 34 | hiltViewModel(key = title) { factory -> 35 | factory.create(url, title) 36 | } 37 | 38 | if (entityType == "product" && title == "讨论") { 39 | LaunchedEffect(sortType) { 40 | if (sortType != viewModel.sortType) { 41 | viewModel.sortType = sortType 42 | viewModel.title = when (sortType) { 43 | ProductSortType.REPLY -> "最近回复" 44 | ProductSortType.HOT -> "热度排序" 45 | ProductSortType.DATELINE -> "最新发布" 46 | } 47 | viewModel.url = "/page?url=/product/feedList?type=feed&id=$id&" + when (sortType) { 48 | ProductSortType.REPLY -> "ignoreEntityById=1" 49 | ProductSortType.HOT -> "listType=rank_score" 50 | ProductSortType.DATELINE -> "ignoreEntityById=1&listType=dateline_desc" 51 | } 52 | viewModel.refresh() 53 | } 54 | } 55 | } 56 | 57 | CommonScreen( 58 | viewModel = viewModel, 59 | refreshState = refreshState, 60 | resetRefreshState = resetRefreshState, 61 | paddingValues = paddingValues, 62 | onViewUser = onViewUser, 63 | onViewFeed = onViewFeed, 64 | onOpenLink = onOpenLink, 65 | onCopyText = onCopyText, 66 | onReport = onReport, 67 | isScrollingUp = isScrollingUp, 68 | ) 69 | 70 | val context = LocalContext.current 71 | viewModel.toastText?.let{ 72 | viewModel.resetToastText() 73 | context.makeToast(it) 74 | } 75 | 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/logic/repository/BlackListRepo.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.logic.repository 2 | 3 | import androidx.lifecycle.LiveData 4 | import com.example.c001apk.compose.di.TopicBlackList 5 | import com.example.c001apk.compose.di.UserBlackList 6 | import com.example.c001apk.compose.logic.dao.StringEntityDao 7 | import com.example.c001apk.compose.logic.model.StringEntity 8 | import kotlinx.coroutines.Dispatchers 9 | import kotlinx.coroutines.flow.Flow 10 | import kotlinx.coroutines.withContext 11 | import javax.inject.Inject 12 | import javax.inject.Singleton 13 | 14 | @Singleton 15 | class BlackListRepo @Inject constructor( 16 | @UserBlackList 17 | private val userBlackListDao: StringEntityDao, 18 | @TopicBlackList 19 | private val topicBlackListDao: StringEntityDao, 20 | ) { 21 | 22 | fun loadAllUserListLive(): LiveData> { 23 | return userBlackListDao.loadAllListLive() 24 | } 25 | 26 | fun loadAllUserListFlow(): Flow> { 27 | return userBlackListDao.loadAllListFlow() 28 | } 29 | 30 | suspend fun insertUid(uid: String) { 31 | userBlackListDao.insert(StringEntity(uid)) 32 | } 33 | 34 | suspend fun insertUidList(list: List) { 35 | userBlackListDao.insertList(list) 36 | } 37 | 38 | suspend fun checkUid(uid: String): Boolean { 39 | return userBlackListDao.isExist(uid) 40 | } 41 | 42 | suspend fun saveUid(uid: String) { 43 | if (!userBlackListDao.isExist(uid)) { 44 | userBlackListDao.insert(StringEntity(uid)) 45 | } 46 | } 47 | 48 | suspend fun deleteUid(uid: String) { 49 | userBlackListDao.delete(uid) 50 | } 51 | 52 | suspend fun deleteAllUser() { 53 | userBlackListDao.deleteAll() 54 | } 55 | 56 | fun loadAllTopicListLive(): LiveData> { 57 | return topicBlackListDao.loadAllListLive() 58 | } 59 | 60 | fun loadAllTopicListFlow(): Flow> { 61 | return topicBlackListDao.loadAllListFlow() 62 | } 63 | 64 | suspend fun insertTopic(topic: String) { 65 | topicBlackListDao.insert(StringEntity(topic)) 66 | } 67 | 68 | suspend fun insertTopicList(list: List) { 69 | topicBlackListDao.insertList(list) 70 | } 71 | 72 | suspend fun checkTopic(topic: String): Boolean { 73 | return withContext(Dispatchers.IO) { 74 | topicBlackListDao.isContain(topic) 75 | } 76 | } 77 | 78 | suspend fun saveTopic(topic: String) { 79 | if (!topicBlackListDao.isExist(topic)) { 80 | topicBlackListDao.insert(StringEntity(topic)) 81 | } 82 | } 83 | 84 | suspend fun deleteTopic(topic: String) { 85 | topicBlackListDao.delete(topic) 86 | } 87 | 88 | suspend fun deleteAllTopic() { 89 | topicBlackListDao.deleteAll() 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /app/src/main/java/com/example/c001apk/compose/view/CircleIndexIndicator.kt: -------------------------------------------------------------------------------- 1 | package com.example.c001apk.compose.view 2 | 3 | import android.animation.ValueAnimator 4 | import android.view.Gravity 5 | import android.view.View 6 | import android.widget.FrameLayout 7 | import androidx.core.view.isVisible 8 | import androidx.viewpager.widget.ViewPager 9 | import net.mikaelzero.mojito.interfaces.IIndicator 10 | import net.mikaelzero.mojito.tools.Utils 11 | 12 | /** 13 | * @Author: MikaelZero 14 | * @CreateDate: 2020/6/13 5:39 PM 15 | * @Description: 16 | */ 17 | class CircleIndexIndicator : IIndicator { 18 | 19 | private var circleIndicator: CircleIndicator? = null 20 | private var originBottomMargin = 10 21 | private var currentBottomMargin = originBottomMargin 22 | 23 | override fun attach(parent: FrameLayout) { 24 | originBottomMargin = Utils.dip2px(parent.context, 16f) 25 | val indexLp = FrameLayout.LayoutParams( 26 | FrameLayout.LayoutParams.WRAP_CONTENT, 27 | Utils.dip2px(parent.context, 36f) 28 | ) 29 | indexLp.gravity = Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL 30 | indexLp.bottomMargin = originBottomMargin 31 | circleIndicator = CircleIndicator(parent.context) 32 | circleIndicator?.gravity = Gravity.CENTER_VERTICAL 33 | circleIndicator?.setLayoutParams(indexLp) 34 | parent.addView(circleIndicator) 35 | } 36 | 37 | override fun onShow(viewPager: ViewPager) { 38 | circleIndicator?.isVisible = true 39 | circleIndicator?.setViewPager(viewPager) 40 | } 41 | 42 | override fun move(moveX: Float, moveY: Float) { 43 | if (circleIndicator == null) { 44 | return 45 | } 46 | val indexLp = circleIndicator!!.layoutParams as FrameLayout.LayoutParams 47 | currentBottomMargin = Math.round(originBottomMargin - moveY / 6f) 48 | if (currentBottomMargin > originBottomMargin) { 49 | currentBottomMargin = originBottomMargin 50 | } 51 | indexLp.bottomMargin = currentBottomMargin 52 | circleIndicator?.setLayoutParams(indexLp) 53 | } 54 | 55 | override fun fingerRelease(isToMax: Boolean, isToMin: Boolean) { 56 | if (circleIndicator == null) { 57 | return 58 | } 59 | var begin = 0 60 | var end = 0 61 | if (isToMax) { 62 | begin = currentBottomMargin 63 | end = originBottomMargin 64 | } 65 | if (isToMin) { 66 | circleIndicator!!.visibility = View.GONE 67 | return 68 | } 69 | val indexLp = circleIndicator!!.layoutParams as FrameLayout.LayoutParams 70 | val valueAnimator = ValueAnimator.ofInt(begin, end) 71 | valueAnimator.addUpdateListener { animation: ValueAnimator -> 72 | indexLp.bottomMargin = animation.getAnimatedValue() as Int 73 | circleIndicator!!.setLayoutParams(indexLp) 74 | } 75 | valueAnimator.setDuration(300).start() 76 | } 77 | } --------------------------------------------------------------------------------