├── 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 |
5 |
6 |
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 | }
--------------------------------------------------------------------------------