├── .github
└── workflows
│ └── main.yml
├── .gitignore
├── LICENSE
├── README.md
├── app
├── .gitignore
├── build.gradle
├── gradle.properties
├── keystore.jks
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── pro
│ │ └── glideim
│ │ ├── App.kt
│ │ ├── IMDataStorage.kt
│ │ ├── MessageListener.kt
│ │ ├── MessageNotifyActionReceiver.kt
│ │ ├── UserConfig.kt
│ │ ├── base
│ │ ├── BaseActivity.kt
│ │ └── BaseFragment.kt
│ │ ├── db
│ │ ├── GlideIMDatabase.kt
│ │ ├── Message.kt
│ │ ├── MessageDao.kt
│ │ ├── Session.kt
│ │ ├── SessionDao.kt
│ │ ├── UserInfo.kt
│ │ └── UserInfoDao.kt
│ │ ├── ui
│ │ ├── Events.kt
│ │ ├── LoginActivity.kt
│ │ ├── MainActivity.kt
│ │ ├── ProgressDialog.kt
│ │ ├── RegisterActivity.kt
│ │ ├── SortedList.java
│ │ ├── SortedListAdapterCallback.java
│ │ ├── SplashActivity.kt
│ │ ├── chat
│ │ │ ├── ChatActivity.kt
│ │ │ ├── MessageListSorter.kt
│ │ │ ├── MySortedList.kt
│ │ │ └── viewholder
│ │ │ │ ├── ChatImageMessageViewData.kt
│ │ │ │ ├── ChatImageMessageViewHolder.kt
│ │ │ │ ├── ChatMessageViewData.kt
│ │ │ │ ├── ChatMessageViewHolder.kt
│ │ │ │ ├── ChatVoiceMessageViewData.kt
│ │ │ │ ├── ChatVoteMessageViewData.kt
│ │ │ │ ├── GroupNotifyViewHolder.kt
│ │ │ │ └── NotifyViewData.kt
│ │ ├── contacts
│ │ │ ├── AddContactsActivity.kt
│ │ │ ├── ContactsFragment.kt
│ │ │ └── SelectContactsActivity.kt
│ │ ├── dev
│ │ │ └── DevOptionsActivity.kt
│ │ ├── group
│ │ │ ├── GroupDetailActivity.kt
│ │ │ └── GroupMemberViewData.kt
│ │ ├── profile
│ │ │ └── ProfileFragment.kt
│ │ └── session
│ │ │ ├── SessionListSorter.kt
│ │ │ ├── SessionViewData.kt
│ │ │ ├── SessionViewHolder.kt
│ │ │ └── SessionsFragment.kt
│ │ ├── utils
│ │ ├── GlideExtension.kt
│ │ ├── GroupAvatarUtils.kt
│ │ ├── ImageUploader.kt
│ │ ├── ItemDecorationFactory.kt
│ │ ├── LetterTouchView.kt
│ │ ├── LifecycleExtensions.kt
│ │ ├── MyBusUtils.java
│ │ ├── RxRequestExtensions.kt
│ │ ├── SwipeRefreshExtension.kt
│ │ ├── ThreadUtils.java
│ │ ├── TimeSpanExtensions.kt
│ │ └── UpdateUtils.kt
│ │ ├── viewholder
│ │ └── EmptyViewHolder.kt
│ │ └── widget
│ │ └── FlowLayout.kt
│ └── res
│ ├── drawable
│ ├── ic_account.xml
│ ├── ic_add.xml
│ ├── ic_add_outline.xml
│ ├── ic_camera.xml
│ ├── ic_check.xml
│ ├── ic_check_circle.xml
│ ├── ic_contacts.xml
│ ├── ic_contacts_add.xml
│ ├── ic_delete_cache.xml
│ ├── ic_dev_mode.xml
│ ├── ic_emoji.xml
│ ├── ic_face.xml
│ ├── ic_file.xml
│ ├── ic_keyboard.xml
│ ├── ic_launcher_background.xml
│ ├── ic_location.xml
│ ├── ic_logout.xml
│ ├── ic_message.xml
│ ├── ic_more_menu.xml
│ ├── ic_notify.xml
│ ├── ic_photos.xml
│ ├── ic_send.xml
│ ├── ic_settings.xml
│ ├── ic_update.xml
│ ├── ic_voice.xml
│ ├── ic_vote.xml
│ ├── ripple_option.xml
│ ├── shape_badge_circle.xml
│ └── shape_option_menu.xml
│ ├── layout
│ ├── activity_add_contacts.xml
│ ├── activity_chat.xml
│ ├── activity_dev_options.xml
│ ├── activity_group_detail.xml
│ ├── activity_login.xml
│ ├── activity_main.xml
│ ├── activity_register.xml
│ ├── activity_select_contacts.xml
│ ├── activity_splash.xml
│ ├── fragment_contacts.xml
│ ├── fragment_profile.xml
│ ├── fragment_session.xml
│ ├── item_chat_group_notify.xml
│ ├── item_chat_image_message.xml
│ ├── item_chat_message.xml
│ ├── item_chat_title.xml
│ ├── item_contacts.xml
│ ├── item_empty.xml
│ ├── item_group_member.xml
│ ├── item_select_contacts.xml
│ ├── item_session.xml
│ ├── layout_multi_message.xml
│ └── pop_message.xml
│ ├── menu
│ ├── menu_chat_group.xml
│ ├── menu_chat_user.xml
│ ├── menu_contacts_add.xml
│ └── menu_home_nav.xml
│ ├── mipmap
│ └── ic_launcher.png
│ ├── values
│ ├── colors.xml
│ ├── id.xml
│ ├── strings.xml
│ └── themes.xml
│ └── xml
│ └── network_security_config.xml
├── build.gradle
├── buildSrc
├── build.gradle
└── src
│ └── main
│ └── groovy
│ └── Config.groovy
├── ci.gradle
├── glide-im-sdk
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── pro
│ │ └── glideim
│ │ └── sdk
│ │ ├── AccountStateListener.java
│ │ ├── Constants.java
│ │ ├── ContactChangeListener.java
│ │ ├── DataStorage.java
│ │ ├── DefaultDataStoreImpl.java
│ │ ├── GlideException.java
│ │ ├── GlideIM.java
│ │ ├── IMAccount.java
│ │ ├── IMContact.java
│ │ ├── IMContactList.java
│ │ ├── IMGroupContact.java
│ │ ├── IMGroupNotifyMessage.java
│ │ ├── IMMessage.java
│ │ ├── IMMessageListener.java
│ │ ├── IMSession.java
│ │ ├── IMSessionList.java
│ │ ├── Logger.java
│ │ ├── MessageChangeListener.java
│ │ ├── Pair.java
│ │ ├── ParameterizedTypeImpl.java
│ │ ├── SessionUpdateListener.java
│ │ ├── SilentObserver.java
│ │ ├── api
│ │ ├── Response.java
│ │ ├── app
│ │ │ ├── AppApi.java
│ │ │ └── ReleaseInfoBean.java
│ │ ├── auth
│ │ │ ├── AuthApi.java
│ │ │ ├── AuthBean.java
│ │ │ ├── AuthDto.java
│ │ │ ├── LoginDto.java
│ │ │ └── RegisterDto.java
│ │ ├── group
│ │ │ ├── AddGroupMemberDto.java
│ │ │ ├── CreateGroupBean.java
│ │ │ ├── CreateGroupDto.java
│ │ │ ├── GetGroupInfoDto.java
│ │ │ ├── GetGroupMemberDto.java
│ │ │ ├── GroupApi.java
│ │ │ ├── GroupInfoBean.java
│ │ │ ├── GroupMemberBean.java
│ │ │ ├── JoinGroupDto.java
│ │ │ └── RemoveMemberDto.java
│ │ ├── msg
│ │ │ ├── AckOfflineMsgDto.java
│ │ │ ├── GetChatHistoryDto.java
│ │ │ ├── GetGroupMessageStateDto.java
│ │ │ ├── GetGroupMsgHistoryDto.java
│ │ │ ├── GetSessionDto.java
│ │ │ ├── GetUserMsgDto.java
│ │ │ ├── GroupMessageBean.java
│ │ │ ├── GroupMessageStateBean.java
│ │ │ ├── MessageBean.java
│ │ │ ├── MessageIDBean.java
│ │ │ ├── MsgApi.java
│ │ │ ├── SessionBean.java
│ │ │ └── UserMsgBean.java
│ │ └── user
│ │ │ ├── ApprovalContactsDto.java
│ │ │ ├── ContactsBean.java
│ │ │ ├── ContactsUidDto.java
│ │ │ ├── GetUserInfoDto.java
│ │ │ ├── ProfileBean.java
│ │ │ ├── RegisterDto.java
│ │ │ ├── TokenBean.java
│ │ │ ├── UserApi.java
│ │ │ └── UserInfoBean.java
│ │ ├── http
│ │ ├── AuthInterceptor.java
│ │ └── RetrofitManager.java
│ │ ├── im
│ │ ├── ConnStateListener.java
│ │ ├── Heartbeat.java
│ │ ├── IMClient.java
│ │ ├── IMClientImpl.java
│ │ ├── KeepAlive.java
│ │ ├── Message.java
│ │ └── MessageListener.java
│ │ ├── messages
│ │ ├── AckMessage.java
│ │ ├── AckRequest.java
│ │ ├── Actions.java
│ │ ├── ChatMessage.java
│ │ ├── CommMessage.java
│ │ ├── GroupMessage.java
│ │ ├── GroupNotify.java
│ │ ├── GroupNotifyMemberChanges.java
│ │ ├── GroupNotifyMemberRemoved.java
│ │ └── RecallMessage.java
│ │ ├── push
│ │ └── NewContactsMessage.java
│ │ ├── utils
│ │ ├── RxUtils.java
│ │ └── SLogger.java
│ │ └── ws
│ │ ├── HeartbeatHandler.java
│ │ ├── MessageListener.java
│ │ ├── NettyWsClient.java
│ │ ├── RetrofitWsClient.java
│ │ ├── WsClient.java
│ │ └── WsInboundChHandler.java
│ └── test
│ └── java
│ └── pro
│ └── glideim
│ └── sdk
│ ├── GlideIMTest.java
│ ├── IMClientTest.java
│ ├── MockUserTest.java
│ ├── TestObserver.java
│ ├── TestResObserver.java
│ ├── api
│ ├── app
│ │ └── AppApiTest.java
│ ├── auth
│ │ └── AuthApiTest.java
│ ├── msg
│ │ └── MsgApiTest.java
│ └── user
│ │ └── UserApiTest.java
│ ├── entity
│ └── IMSessionListTest.java
│ ├── im
│ └── RetrofitWsClientTest.java
│ └── ws
│ └── NettyTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── 3.png
├── a.jpg
└── b.jpg
└── settings.gradle
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Publish & Deploy
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*.*.*'
7 |
8 | jobs:
9 | build-and-deploy:
10 | name: GoIM
11 | runs-on: ubuntu-latest
12 | steps:
13 |
14 | - name: Checkout
15 | uses: actions/checkout@master
16 |
17 | - name: Get Tag
18 | id: get_tag
19 | run: |
20 | echo ::set-output name=TAG::${GITHUB_REF/refs\/tags\//}
21 |
22 | - name: Set Up JDK 11
23 | uses: actions/setup-java@v2
24 | with:
25 | java-version: '11'
26 | distribution: 'temurin'
27 | cache: gradle
28 |
29 | - name: Build With Gradle
30 | run: |
31 | chmod +x gradlew
32 | ./gradlew buildCiRelease -PVERSION_NAME=${{ steps.get_tag.outputs.TAG }} -PVERSION_CODE=${{ steps.get_tag.outputs.TAG }} -PAPK_NAME=glide_im_release_${{ steps.get_tag.outputs.TAG }}.apk
33 |
34 | - name: Create Release
35 | id: create_release
36 | uses: actions/create-release@master
37 | env:
38 | GITHUB_TOKEN: ${{ secrets.GitAction }}
39 | with:
40 | tag_name: ${{ github.ref }}
41 | release_name: GlideIM_release_${{ steps.get_tag.outputs.TAG }}
42 | draft: false
43 | prerelease: false
44 |
45 | - name: Upload Release Asset
46 | id: upload-release-asset
47 | uses: actions/upload-release-asset@master
48 | env:
49 | GITHUB_TOKEN: ${{ secrets.GitAction }}
50 | with:
51 | tag_name: ${{ github.ref }}
52 | upload_url: ${{ steps.create_release.outputs.upload_url }}
53 | asset_path: glide_im_release_${{ steps.get_tag.outputs.TAG }}.apk
54 | asset_name: glide_im_release_${{ steps.get_tag.outputs.TAG }}.apk
55 | asset_content_type: application/gzip
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /.idea
4 | /local.properties
5 | /.idea/caches
6 | /.idea/libraries
7 | /.idea/modules.xml
8 | /.idea/workspace.xml
9 | /.idea/navEditor.xml
10 | /.idea/assetWizardSettings.xml
11 | .DS_Store
12 | /build
13 | /captures
14 | .externalNativeBuild
15 | .cxx
16 | local.properties
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Glide IM
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # GlideIM Android 客户端
2 |
3 | Android UI 部分使用 kotlin 实现, IM 封装成了一个 SDK, 使用 Java 实现.
4 |
5 | ## 基本功能
6 |
7 | - 注册登录
8 | - 好友添加
9 | - 群添加 创建群
10 | - 会话列表
11 | - 联系人列表
12 | - 自动重连
13 | - 消息收发
14 |
15 | ## 下载
16 |
17 | [Download](https://github.com/Glide-IM/Glide-IM-Android/releases)
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | id 'kotlin-android'
4 | id 'com.blankj.bus'
5 | id "org.jetbrains.kotlin.kapt"
6 | }
7 |
8 | bus {
9 | busUtilsClass "pro.glideim.utils.MyBusUtils"
10 | }
11 |
12 | android {
13 | compileSdk 31
14 |
15 | defaultConfig {
16 | applicationId "pro.glideim"
17 | minSdk 26
18 | targetSdk 30
19 | versionCode Config.version
20 | versionName Config.versionName
21 |
22 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
23 | }
24 |
25 | signingConfigs {
26 | release {
27 | keyAlias 'key0'
28 | keyPassword 'password'
29 | storeFile file('keystore.jks')
30 | storePassword 'password'
31 | }
32 | }
33 |
34 | buildTypes {
35 | debug {
36 | signingConfig signingConfigs.release
37 |
38 | buildConfigField "String", "BASE_URL", DEV_API_BASE_URL
39 | }
40 |
41 | release {
42 | minifyEnabled false
43 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
44 | signingConfig signingConfigs.release
45 |
46 | buildConfigField "String", "BASE_URL", RELEASE_API_BASE_URL
47 | }
48 | }
49 | compileOptions {
50 | sourceCompatibility JavaVersion.VERSION_1_8
51 | targetCompatibility JavaVersion.VERSION_1_8
52 | }
53 | kotlinOptions {
54 | jvmTarget = '1.8'
55 | }
56 | packagingOptions {
57 | exclude 'META-INF/INDEX.LIST'
58 | exclude 'META-INF/io.netty.versions.properties'
59 | }
60 | }
61 |
62 | dependencies {
63 |
64 | implementation project(":glide-im-sdk")
65 |
66 | implementation 'androidx.core:core-ktx:1.7.0'
67 | implementation 'androidx.appcompat:appcompat:1.4.1'
68 | implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
69 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
70 | implementation "androidx.viewpager2:viewpager2:1.0.0"
71 |
72 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
73 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2'
74 |
75 | implementation 'com.google.android.material:material:1.6.0-alpha02'
76 |
77 | kapt "androidx.room:room-compiler:2.4.1"
78 | annotationProcessor "androidx.room:room-compiler:2.4.1"
79 | implementation "androidx.room:room-runtime:2.4.1"
80 | implementation "androidx.room:room-ktx:2.4.1"
81 | implementation "androidx.room:room-rxjava2:2.4.1"
82 |
83 | implementation 'com.github.bumptech.glide:glide:4.12.0'
84 | implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
85 |
86 | implementation "com.vanniktech:emoji-google:0.8.0"
87 | implementation "com.vanniktech:emoji-material:0.8.0"
88 | implementation 'com.blankj:utilcodex:1.31.0'
89 | implementation 'com.dengzii:androidktx:1.2.1'
90 | implementation 'com.dengzii:adapter:1.4.2'
91 | }
--------------------------------------------------------------------------------
/app/gradle.properties:
--------------------------------------------------------------------------------
1 | DEV_API_BASE_URL=\"http://api.glide-im.pro/api/\"
2 |
3 | RELEASE_API_BASE_URL=\"http://api.t.glide-im.pro/api/\"
--------------------------------------------------------------------------------
/app/keystore.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glide-im/Glide-IM-Android/19a8f741ceab19dfe12c0cd1c115adce26d8cf4f/app/keystore.jks
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
34 |
35 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/App.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim
2 |
3 | import android.app.Application
4 | import com.dengzii.adapter.SuperAdapter
5 | import com.vanniktech.emoji.EmojiManager
6 | import com.vanniktech.emoji.google.GoogleEmojiProvider
7 | import pro.glideim.sdk.GlideIM
8 |
9 | class App : Application() {
10 |
11 | companion object {
12 | private const val TAG = "App"
13 | }
14 |
15 | override fun onCreate() {
16 | super.onCreate()
17 |
18 | EmojiManager.install(GoogleEmojiProvider())
19 | IMDataStorage.init(this)
20 | MessageListener.init(this)
21 |
22 | // SLogger.setLogger(object : Logger {
23 | // override fun d(tag: String, log: String) {
24 | // Log.d(tag, log)
25 | // }
26 | //
27 | // override fun e(tag: String, t: Throwable) {
28 | // Log.e(tag, "e: ", t)
29 | // }
30 | // })
31 |
32 | val userConfig = UserConfig(this)
33 | GlideIM.init(userConfig.baseUrl)
34 | if (userConfig.enableCache) {
35 | GlideIM.getInstance().dataStorage = IMDataStorage.getInstance()
36 | }
37 | GlideIM.getInstance().setDevice(1)
38 |
39 | SuperAdapter.addDefaultViewHolderForType(
40 | SuperAdapter.Empty::class.java,
41 | pro.glideim.viewholder.EmptyViewHolder::class.java
42 | )
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/MessageNotifyActionReceiver.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.Context
5 | import android.content.Intent
6 |
7 | class MessageNotifyActionReceiver : BroadcastReceiver() {
8 | override fun onReceive(context: Context?, intent: Intent?) {
9 | intent ?: return
10 | context ?: return
11 | val to = intent.getLongExtra("session", 0)
12 | val type = intent.getIntExtra("type", 0)
13 | // GlideIM.getAccount().imSessionList.getSession(type, to).clearUnread()
14 |
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/UserConfig.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim
2 |
3 | import android.content.Context
4 | import com.dengzii.ktx.android.content.Preferences
5 | import com.dengzii.ktx.android.content.preference
6 |
7 | class UserConfig(context: Context) : Preferences(context, "user_config") {
8 | var password by preference("")
9 | var account by preference("")
10 | var lastUpdateCheck by preference("0")
11 | var newestVersion by preference(0)
12 | var baseUrl by preference(BuildConfig.BASE_URL)
13 | var enableCache by preference(false)
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/base/BaseActivity.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.base
2 |
3 | import android.os.Bundle
4 | import android.util.Log
5 | import android.widget.Toast
6 | import androidx.appcompat.app.AppCompatActivity
7 | import com.blankj.utilcode.util.ActivityUtils
8 | import pro.glideim.sdk.GlideIM
9 | import pro.glideim.sdk.IMAccount
10 | import pro.glideim.sdk.im.ConnStateListener
11 | import pro.glideim.sdk.ws.WsClient
12 | import pro.glideim.ui.LoginActivity
13 | import pro.glideim.utils.RequestStateCallback
14 |
15 | abstract class BaseActivity : AppCompatActivity(), RequestStateCallback, ConnStateListener {
16 |
17 | private val TAG = BaseActivity::class.java.simpleName
18 |
19 | abstract val layoutResId: Int
20 |
21 | private var inited = false
22 |
23 | protected var needAuth = true
24 |
25 | open val account: IMAccount? get() = GlideIM.getAccount()
26 |
27 | override fun onCreate(savedInstanceState: Bundle?) {
28 | super.onCreate(savedInstanceState)
29 | setContentView(layoutResId)
30 | }
31 |
32 | override fun onStart() {
33 | super.onStart()
34 | if (!inited) {
35 | initView()
36 | inited = true
37 | }
38 | account?.imClient?.apply {
39 | onStateChange(webSocketClient.state, "")
40 | }
41 | account?.imClient?.addConnStateListener(this)
42 | }
43 |
44 | override fun onResume() {
45 | super.onResume()
46 | if (needAuth && (account == null || account?.uid == 0L)) {
47 | LoginActivity.start(this)
48 | finish()
49 | }
50 | }
51 |
52 | abstract fun initView()
53 |
54 | fun toast(msg: String) {
55 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
56 | }
57 |
58 | override fun onRequestStart() {
59 |
60 | }
61 |
62 | override fun onRequestFinish() {
63 |
64 | }
65 |
66 | override fun onRequestError(t: Throwable) {
67 | toast(t.message ?: "error")
68 | }
69 |
70 | override fun onStop() {
71 | super.onStop()
72 | account?.imClient?.removeConnStateListener(this)
73 | }
74 |
75 | open fun updateConnState(state: String) {
76 |
77 | }
78 |
79 | override fun onStateChange(state: Int, msg: String?) {
80 | Log.d(TAG, "onStateChange: $state")
81 | val s = when (state) {
82 | WsClient.STATE_CLOSED -> {
83 | "disconnected"
84 | }
85 | WsClient.STATE_CONNECTING -> "connecting"
86 | WsClient.STATE_OPENED -> ""
87 | else -> ""
88 | }
89 | runOnUiThread { updateConnState(s) }
90 | }
91 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/base/BaseFragment.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.base
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.Toast
8 | import androidx.annotation.IdRes
9 | import androidx.fragment.app.Fragment
10 | import pro.glideim.sdk.GlideIM
11 | import pro.glideim.sdk.IMAccount
12 | import pro.glideim.sdk.im.ConnStateListener
13 | import pro.glideim.sdk.ws.WsClient
14 | import pro.glideim.utils.RequestStateCallback
15 |
16 | abstract class BaseFragment : Fragment(), RequestStateCallback, ConnStateListener {
17 |
18 | private lateinit var mView: View
19 |
20 | abstract val layoutRes: Int
21 |
22 | abstract fun initView()
23 |
24 | private var inited = false
25 |
26 | protected val account: IMAccount? = GlideIM.getAccount()
27 |
28 | override fun onCreateView(
29 | inflater: LayoutInflater,
30 | container: ViewGroup?,
31 | savedInstanceState: Bundle?
32 | ): View? {
33 | mView = inflater.inflate(layoutRes, null)
34 | return mView
35 | }
36 |
37 | override fun onStart() {
38 | super.onStart()
39 | if (!inited) {
40 | initView()
41 | inited = true
42 | }
43 | }
44 |
45 |
46 | fun findViewById(@IdRes id: Int): T {
47 | return mView.findViewById(id)
48 | }
49 |
50 | fun toast(msg: String) {
51 | Toast.makeText(requireActivity(), msg, Toast.LENGTH_SHORT).show()
52 | }
53 |
54 | override fun onRequestStart() {
55 |
56 | }
57 |
58 | override fun onRequestFinish() {
59 |
60 | }
61 |
62 | override fun onRequestError(t: Throwable) {
63 | t.printStackTrace()
64 | toast(t.message ?: "error")
65 | }
66 |
67 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
68 | super.onViewCreated(view, savedInstanceState)
69 |
70 | account?.imClient?.apply {
71 | onStateChange(webSocketClient.state, "")
72 | addConnStateListener(this@BaseFragment)
73 | }
74 | }
75 |
76 | override fun onDestroyView() {
77 | super.onDestroyView()
78 | account?.imClient?.apply {
79 | removeConnStateListener(this@BaseFragment)
80 | }
81 | }
82 |
83 | open fun updateConnState(state: String) {
84 |
85 | }
86 |
87 | override fun onStateChange(state: Int, msg: String?) {
88 | val s = when (state) {
89 | WsClient.STATE_CLOSED -> {
90 | "disconnected"
91 | }
92 | WsClient.STATE_CONNECTING -> "connecting"
93 | WsClient.STATE_OPENED -> ""
94 | else -> ""
95 | }
96 | activity?.runOnUiThread {
97 | updateConnState(s)
98 | }
99 | }
100 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/GlideIMDatabase.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import android.content.Context
4 | import androidx.room.Database
5 | import androidx.room.Room
6 | import androidx.room.RoomDatabase
7 |
8 | @Database(entities = [Session::class, Message::class, UserInfo::class], version = 2, exportSchema = false)
9 | abstract class GlideIMDatabase : RoomDatabase() {
10 |
11 | abstract fun sessionDao(): SessionDao
12 | abstract fun messageDao(): MessageDao
13 | abstract fun userInfoDao(): UserInfoDao
14 |
15 | companion object {
16 | fun getDb(context: Context): GlideIMDatabase {
17 | return Room.databaseBuilder(context, GlideIMDatabase::class.java, "glide-im-db")
18 | .build()
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/Message.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import pro.glideim.sdk.IMAccount
6 | import pro.glideim.sdk.IMMessage
7 |
8 | @Entity
9 | data class Message(
10 | val uid: Long = 0,
11 | @PrimaryKey
12 | val mid: Long = 0,
13 | val cliSeq: Long = 0,
14 | val from: Long = 0,
15 | val to: Long = 0,
16 | val type: Int = 0,
17 | val sendAt: Long = 0,
18 | val createAt: Long = 0,
19 | val content: String = "",
20 | val targetId: Long = 0,
21 | val targetType: Int = 0,
22 | val state: Int = 0,
23 | val status: Int = 0,
24 | val recallBy:Long = 0,
25 | val seq: Long = 0
26 | ) {
27 | companion object {
28 | fun fromIMMessage(uid: Long, m: IMMessage): Message {
29 | return Message(
30 | uid = uid,
31 | mid = m.mid,
32 | cliSeq = m.cliSeq,
33 | from = m.from,
34 | to = m.to,
35 | type = m.type,
36 | sendAt = m.sendAt,
37 | createAt = m.createAt,
38 | content = m.content,
39 | targetId = m.targetId,
40 | targetType = m.targetType,
41 | state = m.state,
42 | status = m.status,
43 | recallBy = m.recallBy,
44 | seq = m.seq,
45 | )
46 | }
47 | }
48 |
49 | fun toIMMessage(account: IMAccount): IMMessage {
50 | return IMMessage(account).apply {
51 | mid = this@Message.mid
52 | cliSeq = this@Message.cliSeq
53 | from = this@Message.from
54 | to = this@Message.to
55 | type = this@Message.type
56 | sendAt = this@Message.sendAt
57 | createAt = this@Message.createAt
58 | content = this@Message.content
59 | targetId = this@Message.targetId
60 | targetType = this@Message.targetType
61 | state = this@Message.state
62 | status = this@Message.status
63 | seq = this@Message.seq
64 | recallBy = this@Message.recallBy
65 | }
66 |
67 | }
68 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/MessageDao.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.Query
6 | import androidx.room.Update
7 |
8 | @Dao
9 | interface MessageDao {
10 |
11 | @Insert
12 | fun add(vararg message: Message)
13 |
14 | @Update
15 | suspend fun update(vararg s: Message)
16 |
17 | @Query("SELECT * FROM message WHERE mid=:id LIMIT 1")
18 | suspend fun exist(id: Long): List
19 |
20 | @Query("SELECT * FROM Message WHERE uid=:uid AND targetId=:target AND targetType=:targetType")
21 | fun get(uid: Long, targetType: Int, target: Long): List
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/Session.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import pro.glideim.sdk.IMAccount
6 | import pro.glideim.sdk.IMSession
7 |
8 | @Entity
9 | data class Session(
10 | @PrimaryKey
11 | val id: String = "",
12 | val uid: Long = 0,
13 | val to: Long = 0,
14 | val lastMsgSender: Long = 0,
15 | val title: String,
16 | val avatar: String? = null,
17 | val unread: Int = 0,
18 | val updateAt: Long = 0,
19 | val previousUpdateAt: Long = 0,
20 | val type: Int = 0,
21 | val lastMsg: String? = null,
22 | val lastMsgId: Long = 0,
23 | val createAt: Long = 0
24 | ) {
25 | companion object {
26 | fun fromIMSession(uid: Long, s: IMSession): Session {
27 | return Session(
28 | id = "$uid@${s.to}",
29 | uid = uid,
30 | to = s.to,
31 | lastMsgSender = s.lastMsgSender,
32 | title = s.title,
33 | avatar = s.avatar,
34 | unread = s.unread,
35 | updateAt = s.updateAt,
36 | previousUpdateAt = s.previousUpdateAt,
37 | type = s.type,
38 | lastMsg = s.lastMsg,
39 | lastMsgId = s.lastMsgId,
40 | createAt = s.createAt
41 | )
42 | }
43 | }
44 |
45 | fun toImSession(account: IMAccount): IMSession {
46 | return IMSession(account, to, type).apply {
47 | to = this@Session.to
48 | lastMsgSender = this@Session.lastMsgSender
49 | title = this@Session.title
50 | avatar = this@Session.avatar
51 | unread = this@Session.unread
52 | updateAt = this@Session.updateAt
53 | previousUpdateAt = this@Session.previousUpdateAt
54 | type = this@Session.type
55 | lastMsg = this@Session.lastMsg
56 | lastMsgId = this@Session.lastMsgId
57 | createAt = this@Session.createAt
58 | }
59 | }
60 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/SessionDao.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.Query
6 | import androidx.room.Update
7 |
8 | @Dao
9 | interface SessionDao {
10 |
11 | @Insert
12 | suspend fun add(vararg s: Session)
13 |
14 | @Update
15 | suspend fun update(vararg s: Session)
16 |
17 | @Query("SELECT * FROM session WHERE id=:id LIMIT 1")
18 | suspend fun exist(id: String): List
19 |
20 | @Query("SELECT * FROM session WHERE uid=:uid")
21 | fun get(uid: Long): List
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/UserInfo.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Entity
4 | import androidx.room.PrimaryKey
5 | import pro.glideim.sdk.api.user.UserInfoBean
6 |
7 | @Entity
8 | data class UserInfo(
9 | @PrimaryKey
10 | val uid: Long,
11 | val avatar: String,
12 | val nickname: String,
13 | val account: String,
14 | val updateAt: Long
15 | ) {
16 | companion object {
17 | fun fromUserInfoBean(u: UserInfoBean): UserInfo {
18 | return UserInfo(
19 | u.uid,
20 | u.avatar,
21 | u.nickname,
22 | u.account,
23 | updateAt = System.currentTimeMillis()
24 | )
25 | }
26 | }
27 |
28 | fun toUserInfoBean(): UserInfoBean {
29 | return UserInfoBean().apply {
30 | uid = this@UserInfo.uid
31 | avatar = this@UserInfo.avatar
32 | account = this@UserInfo.account
33 | nickname = this@UserInfo.nickname
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/db/UserInfoDao.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.db
2 |
3 | import androidx.room.Dao
4 | import androidx.room.Insert
5 | import androidx.room.Query
6 | import androidx.room.Update
7 |
8 | @Dao
9 | interface UserInfoDao {
10 |
11 | @Insert
12 | suspend fun add(vararg s: UserInfo)
13 |
14 | @Update
15 | suspend fun update(vararg s: UserInfo)
16 |
17 | @Query("SELECT * FROM userinfo WHERE uid=:uid LIMIT 1")
18 | suspend fun exist(uid: Long): List
19 |
20 | @Query("SELECT * FROM userinfo WHERE uid=:uid")
21 | fun get(uid: Long): UserInfo?
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/Events.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui
2 |
3 | import pro.glideim.utils.MyBusUtils
4 |
5 | object Events {
6 | const val EVENT_UPDATE_ALL_CONTACTS = "EVENT_UPDATE_CONTACTS"
7 |
8 | fun updateContacts() {
9 | MyBusUtils.post(EVENT_UPDATE_ALL_CONTACTS)
10 | }
11 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/ProgressDialog.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.DialogFragment
8 | import com.google.android.material.dialog.MaterialAlertDialogBuilder
9 | import com.google.android.material.dialog.MaterialDialogs
10 | import pro.glideim.R
11 |
12 | class ProgressDialog:DialogFragment() {
13 |
14 | override fun onCreateView(
15 | inflater: LayoutInflater,
16 | container: ViewGroup?,
17 | savedInstanceState: Bundle?
18 | ): View? {
19 |
20 | return super.onCreateView(inflater, container, savedInstanceState)
21 | }
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/RegisterActivity.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import com.dengzii.ktx.android.content.update
6 | import com.google.android.material.button.MaterialButton
7 | import com.google.android.material.textfield.TextInputEditText
8 | import pro.glideim.R
9 | import pro.glideim.UserConfig
10 | import pro.glideim.base.BaseActivity
11 | import pro.glideim.sdk.GlideIM
12 | import pro.glideim.utils.io2main
13 | import pro.glideim.utils.request2
14 |
15 | class RegisterActivity : BaseActivity() {
16 |
17 | private val mEtPasswordAgain by lazy { findViewById(R.id.et_password_again) }
18 | private val mBtSubmit by lazy { findViewById(R.id.bt_submit) }
19 | private val mEtPassword by lazy { findViewById(R.id.et_password) }
20 | private val mEtAccount by lazy { findViewById(R.id.et_account) }
21 |
22 |
23 |
24 | override val layoutResId = R.layout.activity_register
25 |
26 | companion object {
27 | @JvmStatic
28 | fun start(context: Context) {
29 | val starter = Intent(context, RegisterActivity::class.java)
30 | context.startActivity(starter)
31 | }
32 | }
33 |
34 | override fun initView() {
35 | needAuth = false
36 | mBtSubmit.setOnClickListener {
37 | submit()
38 | }
39 | }
40 |
41 | private fun submit() {
42 | if (!validate()) {
43 | return
44 | }
45 | val account = mEtAccount.text.toString()
46 | val password = mEtPassword.text.toString()
47 |
48 | GlideIM.register(account, password)
49 | .io2main()
50 | .request2(this) {
51 | toast("Register success!")
52 | UserConfig(this).update {
53 | this.account = account
54 | this.password = password
55 | }
56 | finish()
57 | }
58 | }
59 |
60 | private fun validate(): Boolean {
61 |
62 | val account = mEtAccount.text.toString()
63 | val password = mEtPassword.text.toString()
64 | val passwordAgain = mEtPasswordAgain.text.toString()
65 |
66 | if (account.isBlank() || account.length < 5) {
67 | toast("Please check your account, must contain more than 5 characters")
68 | return false
69 | }
70 | if (password.isBlank() || password.length < 6) {
71 | toast("Please check your password, must contain more than 6 characters")
72 | return false
73 | }
74 | if (password != passwordAgain) {
75 | toast("The password is inconsistent")
76 | return false
77 | }
78 |
79 | return true
80 | }
81 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/SortedListAdapterCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package pro.glideim.ui;
18 |
19 | import androidx.recyclerview.widget.RecyclerView;
20 |
21 | /**
22 | * A {@link androidx.recyclerview.widget.SortedList.Callback} implementation that can bind a {@link androidx.recyclerview.widget.SortedList} to a
23 | * {@link RecyclerView.Adapter}.
24 | */
25 | public abstract class SortedListAdapterCallback extends SortedList.Callback {
26 |
27 | final RecyclerView.Adapter mAdapter;
28 |
29 | /**
30 | * Creates a {@link SortedList.Callback} that will forward data change events to the provided
31 | * Adapter.
32 | *
33 | * @param adapter The Adapter instance which should receive events from the SortedList.
34 | */
35 | public SortedListAdapterCallback(RecyclerView.Adapter adapter) {
36 | mAdapter = adapter;
37 | }
38 |
39 | @Override
40 | public void onInserted(int position, int count) {
41 | mAdapter.notifyItemRangeInserted(position, count);
42 | }
43 |
44 | @Override
45 | public void onRemoved(int position, int count) {
46 | mAdapter.notifyItemRangeRemoved(position, count);
47 | }
48 |
49 | @Override
50 | public void onMoved(int fromPosition, int toPosition) {
51 | mAdapter.notifyItemMoved(fromPosition, toPosition);
52 | }
53 |
54 | @Override
55 | public void onChanged(int position, int count) {
56 | mAdapter.notifyItemRangeChanged(position, count);
57 | }
58 |
59 | @Override
60 | public void onChanged(int position, int count, Object payload) {
61 | mAdapter.notifyItemRangeChanged(position, count, payload);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/SplashActivity.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui
2 |
3 | import com.dengzii.ktx.android.content.update
4 | import com.google.android.material.textview.MaterialTextView
5 | import pro.glideim.BuildConfig
6 | import pro.glideim.MessageListener
7 | import pro.glideim.R
8 | import pro.glideim.UserConfig
9 | import pro.glideim.base.BaseActivity
10 | import pro.glideim.sdk.GlideIM
11 | import pro.glideim.sdk.api.app.AppApi
12 | import pro.glideim.sdk.utils.RxUtils
13 | import pro.glideim.utils.UpdateUtils
14 | import pro.glideim.utils.io2main
15 | import pro.glideim.utils.request
16 | import pro.glideim.utils.request2
17 | import java.util.concurrent.TimeUnit
18 |
19 | class SplashActivity : BaseActivity() {
20 |
21 | private val mTvState by lazy { findViewById(R.id.tv_state) }
22 |
23 | override val layoutResId = R.layout.activity_splash
24 |
25 | override fun initView() {
26 | needAuth = false
27 |
28 | val checkAt = UserConfig(this).lastUpdateCheck.toLong()
29 | val spanMinutes = System.currentTimeMillis() - checkAt / 1000 / 60
30 |
31 | if (spanMinutes > 60) {
32 | AppApi.API.releaseInfo
33 | .timeout(5, TimeUnit.SECONDS)
34 | .map(RxUtils.bodyConverter())
35 | .doOnError {
36 | tryLogin()
37 | }
38 | .request2(this) {
39 | UserConfig(this).update {
40 | lastUpdateCheck = (System.currentTimeMillis() / 1000).toString()
41 | }
42 | if (it.versionCode > BuildConfig.VERSION_CODE) {
43 | UpdateUtils.showUpdate(this, it) { c ->
44 | if (c) {
45 | tryLogin()
46 | }
47 | }
48 | } else {
49 | tryLogin()
50 | }
51 | }
52 | } else {
53 | tryLogin()
54 | }
55 | }
56 |
57 | private fun tryLogin() {
58 | GlideIM.authDefaultAccount()
59 | .io2main()
60 | .request {
61 | onStart {
62 | // mTvState.text = "Connecting to server"
63 | }
64 | onSuccess {
65 | GlideIM.getAccount().setImMessageListener(MessageListener.getInstance())
66 | MainActivity.start(this@SplashActivity)
67 | finish()
68 | }
69 | onError {
70 | it.printStackTrace()
71 | LoginActivity.start(this@SplashActivity)
72 | finish()
73 | }
74 | }
75 | }
76 |
77 | override fun onRequestError(t: Throwable) {
78 | t.printStackTrace()
79 | }
80 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/MessageListSorter.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat
2 |
3 | import com.dengzii.adapter.SuperAdapter
4 | import pro.glideim.ui.SortedListAdapterCallback
5 | import pro.glideim.ui.chat.viewholder.ChatMessageViewData
6 |
7 | class MessageListSorter(adapter: SuperAdapter) :
8 | SortedListAdapterCallback(adapter) {
9 |
10 | override fun compare(o1: ChatMessageViewData, o2: ChatMessageViewData): Int {
11 | var c1 = o1.message.mid
12 | var c2 = o2.message.mid
13 | if (c1 == 0L || c2 == 0L) {
14 | c1 = o1.message.sendAt
15 | c2 = o2.message.sendAt
16 | }
17 | if (c1 == c2) {
18 | return 0
19 | }
20 | return (c2 - c1).toInt()
21 | }
22 |
23 | override fun areContentsTheSame(
24 | oldItem: ChatMessageViewData,
25 | newItem: ChatMessageViewData
26 | ): Boolean {
27 | val om = oldItem.message
28 | val nm = newItem.message
29 | return (om.sendAt == nm.sendAt
30 | && om.content == nm.content
31 | && om.status == nm.status
32 | && om.state == nm.state)
33 | }
34 |
35 | override fun areItemsTheSame(item1: ChatMessageViewData, item2: ChatMessageViewData): Boolean {
36 | if (item1.message.mid == 0L && item2.message.mid == 0L) {
37 | return item1.message.sendAt == item2.message.sendAt
38 | }
39 | return item1.message.mid == item2.message.mid
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/MySortedList.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat
2 |
3 | import pro.glideim.ui.SortedList
4 |
5 |
6 | class MySortedList : List {
7 |
8 | lateinit var l: SortedList
9 |
10 | fun remove(i: T): Boolean {
11 | return l.remove(i)
12 | }
13 |
14 | fun add(m: T) {
15 | l.add(m)
16 | }
17 |
18 | fun clear() {
19 | l.clear()
20 | }
21 |
22 | fun addAll(ms: List) {
23 | l.addAll(ms)
24 | }
25 |
26 | override val size get() = l.size()
27 |
28 | override fun contains(element: T): Boolean {
29 | return l.indexOf(element) != SortedList.INVALID_POSITION
30 | }
31 |
32 | override fun containsAll(elements: Collection): Boolean {
33 | for (element in elements) {
34 | if (!contains(element)) {
35 | return false
36 | }
37 | }
38 | return true
39 | }
40 |
41 | override fun get(index: Int): T {
42 | return l.get(index)
43 | }
44 |
45 | override fun indexOf(element: T): Int {
46 | return l.indexOf(element)
47 | }
48 |
49 | override fun isEmpty(): Boolean {
50 | return l.size() == 0
51 | }
52 |
53 | override fun iterator(): Iterator {
54 | return object : Iterator {
55 | override fun hasNext(): Boolean {
56 | return false
57 | }
58 |
59 | override fun next(): T {
60 | return get(0)
61 | }
62 | }
63 | }
64 |
65 | override fun lastIndexOf(element: T): Int {
66 | return l.indexOf(element)
67 | }
68 |
69 | override fun listIterator(): ListIterator {
70 | return object : ListIterator {
71 | override fun hasNext() = false
72 | override fun hasPrevious() = false
73 | override fun next() = get(0)
74 | override fun nextIndex() = 0
75 | override fun previous() = get(0)
76 | override fun previousIndex() = 0
77 | }
78 | }
79 |
80 | override fun listIterator(index: Int): ListIterator {
81 | return listIterator()
82 | }
83 |
84 | override fun subList(fromIndex: Int, toIndex: Int): List {
85 | return emptyList()
86 | }
87 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/ChatImageMessageViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import pro.glideim.sdk.IMMessage
4 |
5 | class ChatImageMessageViewData(
6 | showTitle: Boolean,
7 | message: IMMessage
8 | ) : ChatMessageViewData(showTitle, message)
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/ChatMessageViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import pro.glideim.sdk.IMMessage
4 |
5 | open class ChatMessageViewData(
6 | var showTitle: Boolean,
7 | var message: IMMessage,
8 | var unknown: Boolean = false
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/ChatVoiceMessageViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import pro.glideim.sdk.IMMessage
4 |
5 | class ChatVoiceMessageViewData(
6 | showTitle: Boolean,
7 | message: IMMessage
8 | ) : ChatMessageViewData(showTitle, message)
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/ChatVoteMessageViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import pro.glideim.sdk.IMMessage
4 |
5 | class ChatVoteMessageViewData(
6 | showTitle: Boolean,
7 | message: IMMessage
8 | ) : ChatMessageViewData(showTitle, message)
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/GroupNotifyViewHolder.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import android.view.ViewGroup
4 | import com.dengzii.adapter.AbsViewHolder
5 | import com.google.android.material.textview.MaterialTextView
6 | import pro.glideim.R
7 |
8 | class GroupNotifyViewHolder(p: ViewGroup) : AbsViewHolder(p) {
9 |
10 | private val mTvContent by lazy { findViewById(R.id.tv_content) }
11 |
12 | override fun onCreate(parent: ViewGroup) {
13 | setContentView(R.layout.item_chat_group_notify)
14 | }
15 |
16 | override fun onBindData(data: NotifyViewData, position: Int) {
17 | mTvContent.text = data.content
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/chat/viewholder/NotifyViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.chat.viewholder
2 |
3 | import pro.glideim.sdk.IMMessage
4 |
5 | data class NotifyViewData(
6 | val msg: IMMessage,
7 | val content: String
8 | ) : ChatMessageViewData(false, msg, false)
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/contacts/AddContactsActivity.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.contacts
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import com.dengzii.ktx.android.content.intentExtra
6 | import com.google.android.material.button.MaterialButton
7 | import com.google.android.material.textfield.TextInputEditText
8 | import pro.glideim.R
9 | import pro.glideim.base.BaseActivity
10 | import pro.glideim.sdk.GlideIM
11 | import pro.glideim.sdk.api.user.ContactsUidDto
12 | import pro.glideim.sdk.api.user.UserApi
13 | import pro.glideim.ui.Events
14 | import pro.glideim.utils.io2main
15 | import pro.glideim.utils.request
16 | import pro.glideim.utils.request2
17 |
18 | class AddContactsActivity : BaseActivity() {
19 | private val mBtQrCode by lazy { findViewById(R.id.bt_qr_code) }
20 | private val mBtSearch by lazy { findViewById(R.id.bt_search) }
21 | private val mEtId by lazy { findViewById(R.id.et_id) }
22 |
23 | private val mSearchGroup by intentExtra("group", false)
24 |
25 | override val layoutResId = R.layout.activity_add_contacts
26 |
27 | companion object {
28 | @JvmStatic
29 | fun start(context: Context, isGroup: Boolean) {
30 | val starter = Intent(context, AddContactsActivity::class.java).apply {
31 | putExtra("group", isGroup)
32 | }
33 | context.startActivity(starter)
34 | }
35 | }
36 |
37 | override fun initView() {
38 | if (mSearchGroup) {
39 | mEtId.hint = "Input Group ID"
40 | } else {
41 | mEtId.hint = "Input User ID"
42 | }
43 | mBtSearch.setOnClickListener {
44 | search()
45 | }
46 | mBtQrCode.setOnClickListener {
47 | toast("TODO")
48 | }
49 | }
50 |
51 | private fun search() {
52 | val id = mEtId.text.toString()
53 | if (id.toLongOrNull() == null || id.length < 2) {
54 | toast("check id")
55 | return
56 | }
57 | if (mSearchGroup) {
58 | GlideIM.getAccount().joinGroup(id.toLong())
59 | .io2main()
60 | .request2(this) {
61 | toast("Group added")
62 | Events.updateContacts()
63 | finish()
64 | }
65 | } else {
66 | UserApi.API.addContacts(ContactsUidDto(id.toLong(), ""))
67 | .request(this) {
68 | toast("Contacts added")
69 | Events.updateContacts()
70 | finish()
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/dev/DevOptionsActivity.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.dev
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import android.view.ContextMenu
7 | import android.view.Menu
8 | import android.view.View
9 | import androidx.core.content.edit
10 | import com.blankj.utilcode.util.AppUtils
11 | import com.dengzii.ktx.android.content.update
12 | import com.dengzii.ktx.android.content.use
13 | import com.google.android.material.switchmaterial.SwitchMaterial
14 | import com.google.android.material.textfield.TextInputEditText
15 | import pro.glideim.BuildConfig
16 | import pro.glideim.R
17 | import pro.glideim.UserConfig
18 | import pro.glideim.base.BaseActivity
19 |
20 | class DevOptionsActivity : BaseActivity() {
21 |
22 | private val mSwEnableCache by lazy { findViewById(R.id.sw_enable_cache) }
23 | private val mEtBaseUrl by lazy { findViewById(R.id.et_base_url) }
24 |
25 | override val layoutResId = R.layout.activity_dev_options
26 |
27 | companion object {
28 | @JvmStatic
29 | fun start(context: Context) {
30 | val starter = Intent(context, DevOptionsActivity::class.java)
31 | context.startActivity(starter)
32 | }
33 | }
34 |
35 | override fun onCreate(savedInstanceState: Bundle?) {
36 | needAuth = false
37 | super.onCreate(savedInstanceState)
38 | }
39 |
40 | override fun initView() {
41 | title = "Developer Options"
42 |
43 | UserConfig(this).use {
44 | mSwEnableCache.isChecked = enableCache
45 | mEtBaseUrl.setText(baseUrl)
46 | }
47 | }
48 |
49 | private fun apply() {
50 | UserConfig(this).update {
51 | enableCache = mSwEnableCache.isChecked
52 | baseUrl = mEtBaseUrl.text.toString()
53 | }
54 | AppUtils.relaunchApp(true)
55 | }
56 |
57 | private fun reset() {
58 | mSwEnableCache.isChecked = false
59 | mEtBaseUrl.setText(BuildConfig.BASE_URL)
60 | }
61 |
62 | override fun onCreateOptionsMenu(menu: Menu?): Boolean {
63 | menu ?: return super.onCreateOptionsMenu(menu)
64 |
65 | val reset = menu.add(0, 1, 0, "Reset")
66 | reset.setShowAsAction(1)
67 | reset.isVisible = true
68 | reset.setOnMenuItemClickListener {
69 | reset()
70 | false
71 | }
72 |
73 | val apply = menu.add(0, 2, 0, "Apply")
74 | apply.setShowAsAction(2)
75 | apply.isVisible = true
76 | apply.setOnMenuItemClickListener {
77 | apply()
78 | false
79 | }
80 |
81 | return true
82 | }
83 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/group/GroupMemberViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.group
2 |
3 | import pro.glideim.sdk.api.group.GroupMemberBean
4 | import pro.glideim.sdk.api.user.UserInfoBean
5 |
6 | data class GroupMemberViewData(
7 | val memberInfo: GroupMemberBean,
8 | val userInfo: UserInfoBean
9 | )
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/session/SessionListSorter.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.session
2 |
3 | import com.dengzii.adapter.SuperAdapter
4 | import pro.glideim.ui.SortedListAdapterCallback
5 |
6 | class SessionListSorter(adapter: SuperAdapter) :
7 | SortedListAdapterCallback(adapter) {
8 |
9 | override fun compare(o1: SessionViewData, o2: SessionViewData): Int {
10 | if (o1.updateAt == o2.updateAt) {
11 | return 0
12 | }
13 | return (o2.updateAt - o1.updateAt).toInt()
14 | }
15 |
16 | override fun areContentsTheSame(oldItem: SessionViewData, newItem: SessionViewData): Boolean {
17 | return oldItem.updateAt == newItem.updateAt &&
18 | oldItem.title == newItem.title &&
19 | oldItem.unread == newItem.unread &&
20 | oldItem.avatar == newItem.avatar &&
21 | oldItem.lastMsg == newItem.lastMsg
22 | }
23 |
24 | override fun areItemsTheSame(item1: SessionViewData, item2: SessionViewData): Boolean {
25 | return item1.to == item2.to && item1.type == item2.type
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/session/SessionViewData.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.session
2 |
3 | import pro.glideim.sdk.IMSession
4 |
5 | class SessionViewData private constructor(
6 | val s: IMSession,
7 | val type: Int,
8 | val to: Long,
9 | val title: String,
10 | var updateAt: Long,
11 | val lastMsg: String,
12 | val avatar: String,
13 | val unread: Int,
14 | val preUpdateAt:Long
15 | ) {
16 | companion object {
17 | fun create(s: IMSession): SessionViewData {
18 | return SessionViewData(
19 | s = s,
20 | type = s.type,
21 | to = s.to,
22 | s.title,
23 | s.updateAt,
24 | s.lastMsg ?: "",
25 | s.avatar,
26 | s.unread,
27 | s.previousUpdateAt
28 | )
29 | }
30 | }
31 |
32 | override fun toString(): String {
33 | return "$type@$to"
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/ui/session/SessionViewHolder.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.ui.session
2 |
3 | import android.view.ViewGroup
4 | import android.widget.TextView
5 | import androidx.appcompat.widget.AppCompatImageView
6 | import com.dengzii.adapter.AbsViewHolder
7 | import com.dengzii.ktx.android.antiShakeClick
8 | import com.dengzii.ktx.android.hide
9 | import com.dengzii.ktx.android.show
10 | import com.google.android.material.textview.MaterialTextView
11 | import pro.glideim.R
12 | import pro.glideim.base.BaseActivity
13 | import pro.glideim.sdk.Constants
14 | import pro.glideim.ui.chat.ChatActivity
15 | import pro.glideim.utils.GroupAvatarUtils
16 | import pro.glideim.utils.loadImageRoundCorners
17 | import pro.glideim.utils.secToTimeSpan
18 |
19 | class SessionViewHolder(v: ViewGroup) : AbsViewHolder(v) {
20 |
21 | private val mTvNewMessage by lazy { findViewById(R.id.tv_new_message) }
22 | private val mTvTime by lazy { findViewById(R.id.tv_time) }
23 | private val mTvContent by lazy { findViewById(R.id.tv_content) }
24 | private val mTvTitle by lazy { findViewById(R.id.tv_title) }
25 | private val mIvAvatar by lazy { findViewById(R.id.iv_avatar) }
26 | private val mVgContainer by lazy { findViewById(R.id.vg_container) }
27 |
28 | override fun onCreate(parent: ViewGroup) {
29 | setContentView(R.layout.item_session)
30 | }
31 |
32 | override fun onBindData(data: SessionViewData, position: Int) {
33 |
34 | if (data.type == Constants.SESSION_TYPE_GROUP) {
35 | GroupAvatarUtils.loadAvatar((context as BaseActivity).account, data.to, 4f, mIvAvatar)
36 | } else {
37 | mIvAvatar.loadImageRoundCorners(data.avatar, 4f)
38 | }
39 |
40 | mTvTitle.text = data.title + "${data.to}"
41 | // mTvContent.text = data.lastMsg
42 | mTvContent.text = data.s.lastMsg
43 | if (data.unread > 0) {
44 | mTvNewMessage.show()
45 | mTvNewMessage.text = data.unread.toString()
46 | } else {
47 | mTvNewMessage.hide()
48 | }
49 | mTvTime.text = data.updateAt.secToTimeSpan()
50 |
51 | mVgContainer.antiShakeClick {
52 | ChatActivity.start(context, data.to, data.type)
53 | }
54 | }
55 |
56 | override fun onBindData(data: SessionViewData, position: Int, payloads: MutableList?) {
57 | super.onBindData(data, position, payloads)
58 |
59 | }
60 |
61 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/GlideExtension.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import android.widget.ImageView
4 | import androidx.annotation.DrawableRes
5 | import com.bumptech.glide.Glide
6 | import com.bumptech.glide.load.resource.bitmap.CircleCrop
7 | import com.bumptech.glide.load.resource.bitmap.RoundedCorners
8 | import com.bumptech.glide.request.RequestOptions
9 | import com.dengzii.ktx.android.dp2px
10 | import pro.glideim.R
11 |
12 | fun ImageView.loadImage(@DrawableRes res: Int) {
13 |
14 | Glide.with(this)
15 | .load(res)
16 | .apply(RequestOptions.fitCenterTransform())
17 | .into(this).clearOnDetach()
18 | }
19 |
20 |
21 | fun ImageView.loadImage(url: String?) {
22 |
23 | if (url.isNullOrEmpty()) {
24 | loadImage(R.mipmap.ic_launcher)
25 | return
26 | }
27 | Glide.with(this)
28 | .load(url)
29 | .apply(RequestOptions.fitCenterTransform())
30 | .placeholder(R.mipmap.ic_launcher)
31 | .into(this)
32 | .clearOnDetach()
33 | }
34 |
35 |
36 | fun ImageView.loadImageClipCircle(url: String?) {
37 |
38 | if (url.isNullOrEmpty()) {
39 | return
40 | }
41 | Glide.with(this)
42 | .load(url)
43 | .apply(RequestOptions.bitmapTransform(CircleCrop()))
44 | .placeholder(R.mipmap.ic_launcher)
45 | .into(this)
46 | .clearOnDetach()
47 | }
48 |
49 | fun ImageView.loadImageRoundCorners(url: String?, radius: Float = 10f) {
50 |
51 | if (url.isNullOrEmpty()) {
52 | return
53 | }
54 | Glide.with(this)
55 | .load(url)
56 | .apply(RequestOptions.bitmapTransform(RoundedCorners(radius.dp2px())))
57 | .placeholder(R.mipmap.ic_launcher)
58 | .into(this)
59 | .clearOnDetach()
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/ImageUploader.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | object ImageUploader {
4 |
5 | fun upload() {
6 |
7 | }
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/ItemDecorationFactory.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Paint
5 | import android.graphics.Rect
6 | import android.view.View
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.dengzii.ktx.android.dp2px
9 |
10 |
11 | object ItemDecorationFactory {
12 |
13 | fun createOffset(
14 | dp: Int
15 | ): RecyclerView.ItemDecoration {
16 |
17 | return object : RecyclerView.ItemDecoration() {
18 | val size = dp.toFloat().dp2px()
19 | override fun getItemOffsets(
20 | outRect: Rect,
21 | view: View,
22 | parent: RecyclerView,
23 | state: RecyclerView.State
24 | ) {
25 | super.getItemOffsets(outRect, view, parent, state)
26 | outRect.set(0, size / 2, 0, size / 2)
27 | }
28 | }
29 | }
30 |
31 | fun createDivider(
32 | dpSize: Float, color: Int,
33 | marginStart: Float = 0f,
34 | marginEnd: Float = 0f
35 | ): RecyclerView.ItemDecoration {
36 |
37 | return object : RecyclerView.ItemDecoration() {
38 | val size = dpSize.dp2px()
39 | val paint by lazy {
40 | Paint().apply {
41 | setColor(color)
42 | strokeWidth = size.toFloat()
43 | }
44 | }
45 | val startX = marginStart.dp2px().toFloat()
46 |
47 | override fun getItemOffsets(
48 | outRect: Rect, view: View,
49 | parent: RecyclerView, state: RecyclerView.State
50 | ) {
51 | super.getItemOffsets(outRect, view, parent, state)
52 | outRect.set(0, size / 2, 0, size / 2)
53 | }
54 |
55 | override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
56 | super.onDrawOver(c, parent, state)
57 | for (i in 0 until parent.childCount - 1) {
58 | val view = parent.getChildAt(i)
59 | val top = view.bottom.toFloat()
60 | // val left = view.paddingLeft + size
61 | val right = (view.width - view.paddingRight - size).toFloat()
62 | // val bottom = top + size
63 | c.drawLine(startX, top, right - marginEnd.dp2px(), top, paint)
64 | }
65 | }
66 | }
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/LifecycleExtensions.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import androidx.lifecycle.Lifecycle
4 | import androidx.lifecycle.LifecycleEventObserver
5 | import androidx.lifecycle.LifecycleOwner
6 |
7 |
8 | fun LifecycleOwner.onState(state: Lifecycle.State, callback: () -> Unit) {
9 | lifecycle.addObserver(object : LifecycleEventObserver {
10 | override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
11 | if (event.targetState == state) {
12 | callback.invoke()
13 | lifecycle.removeObserver(this)
14 | }
15 | }
16 | })
17 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/SwipeRefreshExtension.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
4 | import pro.glideim.R
5 |
6 |
7 | var SwipeRefreshLayout.onRefreshCallback: (() -> Unit)?
8 | set(value) {
9 | setTag(R.id.tag_swipe_refresh_on_refresh_listener, value)
10 | }
11 | get() {
12 | return getTag(R.id.tag_swipe_refresh_on_refresh_listener) as? () -> Unit
13 | }
14 |
15 | fun SwipeRefreshLayout.onRefresh(callback: () -> Unit) {
16 | setOnRefreshListener {
17 | callback.invoke()
18 | }
19 | onRefreshCallback = callback
20 | }
21 |
22 | fun SwipeRefreshLayout.startRefresh() {
23 | isRefreshing = true
24 | onRefreshCallback?.invoke()
25 | }
26 |
27 | fun SwipeRefreshLayout.finishRefresh() {
28 | isRefreshing = false
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/TimeSpanExtensions.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import java.util.*
4 |
5 |
6 | private const val hourSec = 60 * 60
7 | private const val daySec = hourSec * 24
8 | private const val mothSec = daySec * 30
9 |
10 | fun Long.secToTimeSpan(): String {
11 |
12 | val instance = Calendar.getInstance(Locale.getDefault())
13 | instance.time = Date(this * 1000)
14 | val today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH)
15 |
16 | val m = instance.get(Calendar.MONTH) + 1
17 | val d = instance.get(Calendar.DAY_OF_MONTH)
18 | val h = instance.get(Calendar.HOUR_OF_DAY)
19 | val min = instance.get(Calendar.MINUTE)
20 |
21 | return when (today - d) {
22 | 0 -> "$h:${if (min < 10) "0" else ""}$min"
23 | 1 -> "昨天"
24 | 2 -> "前天"
25 | else -> "$m-$d"
26 | }
27 |
28 | // return when {
29 | // span <= 10 -> "刚刚"
30 | // span <= 60 -> "$span 秒前"
31 | // span <= 30 * 60 -> "${span / 60} 分钟前"
32 | // span <= hourSec -> "半小时时前"
33 | // span <= daySec -> "${span / hourSec} 小时前"
34 | // span <= daySec * 2 -> "昨天"
35 | // span <= daySec * 3 -> "前天"
36 | // span <= mothSec -> "${span / daySec} 天前"
37 | // else -> "${span / mothSec} 个月前"
38 | // }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/utils/UpdateUtils.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.utils
2 |
3 | import android.content.Context
4 | import android.content.Intent
5 | import android.net.Uri
6 | import androidx.appcompat.app.AlertDialog
7 | import com.dengzii.ktx.format
8 | import pro.glideim.BuildConfig
9 | import pro.glideim.sdk.api.app.ReleaseInfoBean
10 | import java.util.*
11 |
12 | object UpdateUtils {
13 |
14 | fun showUpdate(context: Context, info: ReleaseInfoBean, callback: (cancel: Boolean) -> Unit) {
15 | val builder = AlertDialog.Builder(context)
16 | val date = Date(info.updateAt * 1000)
17 | val format = date.format("yyyy MM.dd")
18 | builder.setCancelable(false)
19 | builder.setTitle("New Version ${info.versionName}")
20 | builder.setMessage(
21 | "Current: ${BuildConfig.VERSION_NAME}\n" +
22 | "Date: $format\n" +
23 | "What's New: \n" +
24 | "${info.description}\n"
25 | )
26 | builder.setPositiveButton("Download") { d, _ ->
27 | val intent = Intent(Intent.ACTION_VIEW)
28 | intent.data = Uri.parse(info.downloadUrl)
29 | context.startActivity(intent)
30 | d.dismiss()
31 | callback(false)
32 | }
33 | builder.setNegativeButton("Cancel") { d, _ ->
34 | d.dismiss()
35 | callback(true)
36 | }
37 | builder.create().show()
38 | }
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/pro/glideim/viewholder/EmptyViewHolder.kt:
--------------------------------------------------------------------------------
1 | package pro.glideim.viewholder
2 |
3 | import android.view.ViewGroup
4 | import com.dengzii.adapter.AbsViewHolder
5 | import com.dengzii.adapter.SuperAdapter
6 |
7 | class EmptyViewHolder(v: ViewGroup) : AbsViewHolder(v) {
8 |
9 | override fun onCreate(parent: ViewGroup) {
10 |
11 | }
12 |
13 | override fun onBindData(data: SuperAdapter.Empty, position: Int) {
14 |
15 | }
16 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_account.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_add_outline.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_camera.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_check_circle.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contacts.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_contacts_add.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_delete_cache.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dev_mode.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_emoji.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_face.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_file.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_keyboard.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_location.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_logout.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_message.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more_menu.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notify.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_photos.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_send.xml:
--------------------------------------------------------------------------------
1 |
8 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_settings.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_update.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_voice.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_vote.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
16 |
19 |
22 |
23 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ripple_option.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_badge_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/shape_option_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_add_contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
36 |
37 |
40 |
41 |
46 |
47 |
48 |
49 |
55 |
56 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_dev_options.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
14 |
21 |
22 |
23 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_group_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
13 |
14 |
22 |
23 |
28 |
29 |
30 |
31 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_register.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
19 |
20 |
28 |
29 |
30 |
34 |
35 |
42 |
43 |
44 |
45 |
49 |
50 |
57 |
58 |
59 |
66 |
67 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_select_contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
26 |
27 |
28 |
38 |
39 |
40 |
41 |
45 |
46 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_splash.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_session.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
22 |
23 |
24 |
25 |
29 |
30 |
34 |
35 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_chat_group_notify.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_chat_title.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_empty.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_group_member.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
16 |
17 |
23 |
24 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_select_contacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
29 |
30 |
39 |
40 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_session.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
30 |
31 |
43 |
44 |
45 |
52 |
53 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pop_message.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_chat_group.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_chat_user.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_contacts_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_home_nav.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glide-im/Glide-IM-Android/19a8f741ceab19dfe12c0cd1c115adce26d8cf4f/app/src/main/res/mipmap/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #0097a7
5 | #56c8d8
6 | #006978
7 | #fb8c00
8 | #ffbd45
9 | #c25e00
10 | #333
11 | #5C5C5C
12 |
13 | #FFFFFF
14 | #DCDCDC
15 |
16 | #E3E3E3
17 |
18 | #fff
19 | #ffcccccc
20 |
--------------------------------------------------------------------------------
/app/src/main/res/values/id.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | GlideIM
3 | Login
4 | Account
5 | Password
6 | Sign In
7 | submit
8 | Sign Up
9 | Forgot Password?
10 | or
11 | Register
12 | Password again
13 | SignIn
14 | Home
15 | Messages
16 | Profile
17 | Sign Out
18 | Contacts
19 | UID or Group ID
20 | Search
21 | Scan QR Code
22 | QR Code
23 | New Contacts
24 | Chat
25 | Notifications
26 | Add Friend
27 | Add Group
28 | Create Group
29 | Search User
30 | Join Group
31 | Members
32 | Invite
33 | Exit And Delete
34 | Group Members
35 | Clean Cache
36 | Update Profile
37 | Settings
38 | Complete
39 | Recall
40 | Api Base URL
41 | Enable Cache
42 |
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
22 |
23 |
24 |
28 |
29 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply from: "ci.gradle"
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | mavenCentral()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:4.1.3'
11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
12 | classpath 'com.blankj:bus-gradle-plugin:2.6'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | task clean(type: Delete) {
20 | delete rootProject.buildDir
21 | }
--------------------------------------------------------------------------------
/buildSrc/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | // config repositories
3 | repositories {
4 |
5 | }
6 |
7 | // config gradle project type
8 | // we config groovy and java-gradle-plugin
9 | // this means
10 | apply {
11 | plugin 'groovy'
12 | plugin 'java-gradle-plugin'
13 | }
14 |
15 | // import gradle api and groovy lang
16 | dependencies {
17 | implementation gradleApi()
18 | implementation localGroovy()
19 | }
--------------------------------------------------------------------------------
/buildSrc/src/main/groovy/Config.groovy:
--------------------------------------------------------------------------------
1 | class Config {
2 |
3 | static version = 144
4 | static versionName = "1.4.4"
5 | }
--------------------------------------------------------------------------------
/ci.gradle:
--------------------------------------------------------------------------------
1 | // ./gradlew buildCiRelease -PVERSION_NAME=1.0.0 -PVERSION_CODE=1 -PAPK_NAME=a.apk
2 |
3 | task initBuildVersion {
4 | def p = gradle.startParameter.projectProperties
5 | if(!p.containsKey("VERSION_NAME")){
6 | return
7 | }
8 | Config.versionName = VERSION_NAME.toString().replaceAll("v", "")
9 | Config.version = Integer.parseInt(VERSION_CODE.toString().replaceAll("[^0-9]", ""))
10 | }
11 |
12 | task buildCiRelease(dependsOn: ["initBuildVersion", "app:assembleRelease"], type: Copy) {
13 | from "${rootProject.projectDir.path}/app/build/outputs/apk/release/"
14 | into "./"
15 | include('*.apk')
16 | exclude('*.json')
17 |
18 | doLast {
19 | File f = new File("app-release.apk")
20 | f.renameTo(APK_NAME)
21 | }
22 | }
23 |
24 | buildCiRelease.mustRunAfter initBuildVersion
--------------------------------------------------------------------------------
/glide-im-sdk/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/glide-im-sdk/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.library'
3 | id 'kotlin-android'
4 | }
5 |
6 | android {
7 | compileSdk 31
8 |
9 | defaultConfig {
10 | minSdk 26
11 | targetSdk 31
12 | versionCode 1
13 | versionName "1.0"
14 |
15 | vectorDrawables.useSupportLibrary true
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | consumerProguardFiles "consumer-rules.pro"
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | compileOptions {
27 | sourceCompatibility JavaVersion.VERSION_1_8
28 | targetCompatibility JavaVersion.VERSION_1_8
29 | }
30 | kotlinOptions {
31 | jvmTarget = '1.8'
32 | }
33 | testOptions {
34 | unitTests.all {
35 | useJUnitPlatform()
36 | }
37 | }
38 | }
39 |
40 | dependencies {
41 |
42 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
43 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
44 |
45 | implementation 'androidx.core:core-ktx:1.7.0'
46 | implementation 'io.netty:netty-all:4.1.70.Final'
47 |
48 |
49 | implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
50 | implementation 'com.squareup.retrofit2:retrofit:2.9.0'
51 | implementation 'com.squareup.okhttp3:okhttp:4.9.0'
52 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
53 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
54 | implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
55 |
56 | implementation 'io.reactivex.rxjava2:rxjava:2.1.9'
57 | implementation 'com.squareup.retrofit2:retrofit:2.9.0'
58 | implementation 'com.squareup.okhttp3:okhttp:4.9.0'
59 | implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
60 | implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
61 | }
--------------------------------------------------------------------------------
/glide-im-sdk/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/glide-im/Glide-IM-Android/19a8f741ceab19dfe12c0cd1c115adce26d8cf4f/glide-im-sdk/consumer-rules.pro
--------------------------------------------------------------------------------
/glide-im-sdk/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/AccountStateListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public interface AccountStateListener {
4 | void onLoggedIn();
5 |
6 | void onReconnect();
7 |
8 | void onKickOut(String deviceInfo);
9 | }
10 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/Constants.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public class Constants {
4 |
5 | public static final int GROUP_MEMBER_OWNER = 1;
6 | public static final int GROUP_MEMBER_ADMIN = 2;
7 | public static final int GROUP_MEMBER = 3;
8 |
9 | public static final int SESSION_TYPE_USER = 1;
10 | public static final int SESSION_TYPE_GROUP = 2;
11 | public static final int SESSION_TYPE_DEVICE = 3;
12 |
13 | public static final int MESSAGE_TYPE_GROUP_NOTIFY = -1;
14 | public static final int MESSAGE_TYPE_TEXT = 1;
15 | public static final int MESSAGE_TYPE_IMAGE = 2;
16 | public static final int MESSAGE_TYPE_VOICE = 3;
17 | public static final int MESSAGE_TYPE_RECALL = 100;
18 | }
19 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/ContactChangeListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public interface ContactChangeListener {
4 | void onNewContact(IMContact c);
5 |
6 | void onContactUpdate(IMContact contact);
7 |
8 | void onContactRemove(IMContact contact);
9 | }
10 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/DataStorage.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import java.util.List;
4 |
5 | import pro.glideim.sdk.api.group.GroupInfoBean;
6 | import pro.glideim.sdk.api.user.UserInfoBean;
7 |
8 | public interface DataStorage {
9 |
10 | long getDefaultAccountUid();
11 |
12 | void storeToken(long uid, String token);
13 |
14 | String loadToken(long uid);
15 |
16 | void storeTempUserInfo(UserInfoBean userInfoBean);
17 |
18 | UserInfoBean loadTempUserInfo(long uid);
19 |
20 | void storeTempGroupInfo(GroupInfoBean groupInfoBean);
21 |
22 | GroupInfoBean loadTempGroupInfo(long gid);
23 |
24 | void storeSession(long uid, IMSession session);
25 |
26 | List loadSessions(long uid);
27 |
28 | List loadMessage(long uid, int type, long to);
29 |
30 | void storeMessage(IMMessage message);
31 | }
32 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/DefaultDataStoreImpl.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import java.util.ArrayList;
4 | import java.util.HashMap;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import pro.glideim.sdk.api.group.GroupInfoBean;
9 | import pro.glideim.sdk.api.user.UserInfoBean;
10 |
11 | public class DefaultDataStoreImpl implements DataStorage {
12 |
13 |
14 | private static final Map sTempUserInfo = new HashMap<>();
15 | private static final Map sTempGroupInfo = new HashMap<>();
16 | private static final Map> sTempSession = new HashMap<>();
17 |
18 | private String token = "";
19 | private long uid = 0;
20 |
21 | @Override
22 | public long getDefaultAccountUid() {
23 | return uid;
24 | }
25 |
26 | @Override
27 | public void storeToken(long uid, String token) {
28 | this.uid = uid;
29 | this.token = token;
30 | }
31 |
32 | @Override
33 | public String loadToken(long uid) {
34 | return token;
35 | }
36 |
37 | @Override
38 | public void storeTempUserInfo(UserInfoBean userInfoBean) {
39 | sTempUserInfo.put(userInfoBean.getUid(), userInfoBean);
40 | }
41 |
42 | @Override
43 | public UserInfoBean loadTempUserInfo(long uid) {
44 | return sTempUserInfo.get(uid);
45 | }
46 |
47 | @Override
48 | public void storeTempGroupInfo(GroupInfoBean groupInfoBean) {
49 | sTempGroupInfo.put(groupInfoBean.getGid(), groupInfoBean);
50 | }
51 |
52 | @Override
53 | public GroupInfoBean loadTempGroupInfo(long gid) {
54 | return sTempGroupInfo.get(gid);
55 | }
56 |
57 | @Override
58 | public void storeSession(long uid, IMSession session) {
59 | if (!sTempSession.containsKey(uid)) {
60 | sTempSession.put(uid, new HashMap<>());
61 | }
62 | sTempSession.get(uid).put(session.to, session);
63 | }
64 |
65 | @Override
66 | public List loadSessions(long uid) {
67 | if (!sTempSession.containsKey(uid)) {
68 | sTempSession.put(uid, new HashMap<>());
69 | }
70 | return new ArrayList<>(sTempSession.get(uid).values());
71 | }
72 |
73 | @Override
74 | public List loadMessage(long uid, int type, long to) {
75 | return new ArrayList<>();
76 | }
77 |
78 | @Override
79 | public void storeMessage(IMMessage message) {
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/GlideException.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public class GlideException extends Exception {
4 | public GlideException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/IMContact.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import io.reactivex.Single;
4 | import pro.glideim.sdk.api.user.ContactsBean;
5 | import pro.glideim.sdk.api.user.UserInfoBean;
6 | import pro.glideim.sdk.utils.SLogger;
7 |
8 | public class IMContact {
9 |
10 | public static final int TYPE_GROUP = 2;
11 | public static final int TYPE_USER = 1;
12 |
13 | public String title;
14 | public String avatar;
15 | public long id;
16 | public int type;
17 | private IMAccount account;
18 |
19 | public static IMContact fromContactsBean(ContactsBean contactsBean, IMContactList contactList, IMAccount account) {
20 | if (contactsBean.getType() == TYPE_GROUP) {
21 | return new IMGroupContact(account, contactList,contactsBean);
22 | }
23 | IMContact c = new IMContact();
24 | c.type = contactsBean.getType();
25 | c.id = contactsBean.getId();
26 | c.title = contactsBean.getRemark();
27 | c.account = account;
28 | return c;
29 | }
30 |
31 | public Single extends IMContact> update() {
32 | if (type == Constants.SESSION_TYPE_USER) {
33 | return GlideIM.getUserInfo(id)
34 | .doOnSuccess(this::setDetail)
35 | .map(userInfoBeans -> IMContact.this);
36 | }
37 | SLogger.d("IMContacts", "unknown contacts type " + type);
38 | return Single.just(this);
39 | }
40 |
41 | private void setDetail(UserInfoBean userInfoBean) {
42 | title = userInfoBean.getNickname();
43 | avatar = userInfoBean.getAvatar();
44 | }
45 |
46 | @Override
47 | public String toString() {
48 | return "IMContacts{" +
49 | "title='" + title + '\'' +
50 | ", avatar='" + avatar + '\'' +
51 | ", id=" + id +
52 | ", type=" + type +
53 | '}';
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/IMContactList.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.TreeMap;
6 |
7 | import pro.glideim.sdk.utils.SLogger;
8 |
9 | public class IMContactList {
10 |
11 | private final TreeMap contactsUser = new TreeMap<>();
12 | private final TreeMap contactsGroup = new TreeMap<>();
13 | private final IMAccount account;
14 | private final List contactChangeListeners = new ArrayList<>();
15 |
16 | public IMContactList(IMAccount account) {
17 | this.account = account;
18 | }
19 |
20 | public void addContactChangeListener(ContactChangeListener l) {
21 | this.contactChangeListeners.add(l);
22 | }
23 |
24 | public void removeContactChangeListener(ContactChangeListener l) {
25 | this.contactChangeListeners.remove(l);
26 | }
27 |
28 | public IMContact getUser(long uid) {
29 | return contactsUser.get(uid);
30 | }
31 |
32 | public IMGroupContact getGroup(long gid) {
33 | return contactsGroup.get(gid);
34 | }
35 |
36 | public void removeGroup(long gid) {
37 | IMContact contact = contactsGroup.remove(gid);
38 | onRemove(contact);
39 | }
40 |
41 | public void removeUser(long uid) {
42 | IMContact contact = contactsUser.remove(uid);
43 | onRemove(contact);
44 | }
45 |
46 | private void onRemove(IMContact c) {
47 | for (ContactChangeListener l : contactChangeListeners) {
48 | l.onContactRemove(c);
49 | }
50 | }
51 |
52 | void onUpdate(IMContact c) {
53 | for (ContactChangeListener l : contactChangeListeners) {
54 | l.onContactUpdate(c);
55 | }
56 | }
57 |
58 | public void addContacts(IMContact contact) {
59 | switch (contact.type) {
60 | case IMContact.TYPE_GROUP:
61 | if (!(contact instanceof IMGroupContact)) {
62 | SLogger.e("IMContactList", new IllegalArgumentException("group contact not instance of IMGroupContact"));
63 | return;
64 | }
65 | contactsGroup.put(contact.id, ((IMGroupContact) contact));
66 | break;
67 | case IMContact.TYPE_USER:
68 | contactsUser.put(contact.id, contact);
69 | break;
70 | default:
71 | SLogger.e("IMContactList", new IllegalArgumentException("unknown contact type"));
72 | return;
73 | }
74 | for (ContactChangeListener l : contactChangeListeners) {
75 | l.onNewContact(contact);
76 | }
77 | }
78 |
79 | public List getAll() {
80 | return new ArrayList<>(contactsUser.values());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/IMGroupNotifyMessage.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import pro.glideim.sdk.messages.GroupNotify;
4 | import pro.glideim.sdk.messages.GroupNotifyMemberChanges;
5 |
6 | public class IMGroupNotifyMessage extends IMMessage {
7 |
8 | public GroupNotify notify;
9 |
10 | public IMGroupNotifyMessage(IMAccount account, GroupNotify notify) {
11 | super(account);
12 | this.notify = notify;
13 | this.setMid(notify.getMid());
14 | this.setCliSeq(0);
15 | this.setFrom(0);
16 | this.setTo(notify.getGid());
17 | this.setSeq(notify.getSeq());
18 | this.setType(Constants.MESSAGE_TYPE_GROUP_NOTIFY);
19 | this.setSendAt(notify.getTimestamp());
20 | this.setContent("-");
21 | this.setTarget(Constants.SESSION_TYPE_GROUP, notify.getGid());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/IMMessageListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import pro.glideim.sdk.push.NewContactsMessage;
4 |
5 | public interface IMMessageListener {
6 | void onNotify(String msg);
7 |
8 | void onNewMessage(IMMessage message);
9 |
10 | void onNewContact(NewContactsMessage c);
11 |
12 | void onKickOut();
13 |
14 | void onTokenInvalid();
15 | }
16 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/Logger.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public interface Logger {
4 | void d(String tag, String log);
5 |
6 | void e(String tag, Throwable t);
7 | }
8 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/MessageChangeListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | public interface MessageChangeListener {
6 | void onChange(long mid, @NonNull IMMessage message);
7 |
8 | void onInsertMessage(long mid, @NonNull IMMessage message);
9 |
10 | void onNewMessage(@NonNull IMMessage message);
11 | }
12 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/Pair.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public class Pair {
4 | public final K k;
5 | public final V v;
6 |
7 | public Pair(K k, V v) {
8 | this.k = k;
9 | this.v = v;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/ParameterizedTypeImpl.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import java.lang.reflect.ParameterizedType;
4 | import java.lang.reflect.Type;
5 |
6 | public class ParameterizedTypeImpl implements ParameterizedType {
7 | private final Class> raw;
8 | private final Type[] args;
9 |
10 | public ParameterizedTypeImpl(Class> raw, Type[] args) {
11 | this.raw = raw;
12 | this.args = args != null ? args : new Type[0];
13 | }
14 |
15 | @Override
16 | public Type[] getActualTypeArguments() {
17 | return args;
18 | }
19 |
20 | @Override
21 | public Type getRawType() {
22 | return raw;
23 | }
24 |
25 | @Override
26 | public Type getOwnerType() {
27 | return null;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/SessionUpdateListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | public interface SessionUpdateListener {
4 | void onUpdate(IMSession session);
5 |
6 | void onNewSession(IMSession session);
7 | }
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/SilentObserver.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk;
2 |
3 | import androidx.annotation.NonNull;
4 |
5 | import org.json.JSONStringer;
6 |
7 | import io.reactivex.Observer;
8 | import io.reactivex.SingleObserver;
9 | import io.reactivex.disposables.Disposable;
10 | import pro.glideim.sdk.utils.SLogger;
11 |
12 | public class SilentObserver implements Observer, SingleObserver {
13 |
14 | @Override
15 | public void onSubscribe(@NonNull Disposable d) {
16 |
17 | }
18 |
19 | @Override
20 | public void onSuccess(@NonNull T t) {
21 | onNext(t);
22 | }
23 |
24 | @Override
25 | public void onNext(@NonNull T t) {
26 |
27 | }
28 |
29 | @Override
30 | public void onError(@NonNull Throwable e) {
31 | StackTraceElement stackTraceElement = e.getStackTrace()[0];
32 | SLogger.d("SilentObserver", e.getMessage() + " : " + stackTraceElement.toString());
33 | }
34 |
35 | @Override
36 | public void onComplete() {
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/Response.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api;
2 |
3 | public class Response {
4 | private int code;
5 | private String msg;
6 | private T data;
7 |
8 | public boolean success(){
9 | return code == 100;
10 | }
11 |
12 | public int getCode() {
13 | return code;
14 | }
15 |
16 | public void setCode(int code) {
17 | this.code = code;
18 | }
19 |
20 | public String getMsg() {
21 | return msg;
22 | }
23 |
24 | public void setMsg(String msg) {
25 | this.msg = msg;
26 | }
27 |
28 | public T getData() {
29 | return data;
30 | }
31 |
32 | public void setData(T data) {
33 | this.data = data;
34 | }
35 | }
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/app/AppApi.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.app;
2 |
3 | import io.reactivex.Observable;
4 | import pro.glideim.sdk.api.Response;
5 | import pro.glideim.sdk.http.RetrofitManager;
6 | import retrofit2.http.GET;
7 |
8 | public interface AppApi {
9 | AppApi API = RetrofitManager.create(AppApi.class);
10 |
11 | @GET("app/release")
12 | Observable> getReleaseInfo();
13 | }
14 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/app/ReleaseInfoBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.app;
2 |
3 | public class ReleaseInfoBean {
4 | private long versionCode;
5 | private String versionName;
6 | private long updateAt;
7 | private String downloadUrl;
8 | private String description;
9 |
10 | public long getVersionCode() {
11 | return versionCode;
12 | }
13 |
14 | public void setVersionCode(long versionCode) {
15 | this.versionCode = versionCode;
16 | }
17 |
18 | public String getVersionName() {
19 | return versionName;
20 | }
21 |
22 | public void setVersionName(String versionName) {
23 | this.versionName = versionName;
24 | }
25 |
26 | public long getUpdateAt() {
27 | return updateAt;
28 | }
29 |
30 | public void setUpdateAt(long updateAt) {
31 | this.updateAt = updateAt;
32 | }
33 |
34 | public String getDownloadUrl() {
35 | return downloadUrl;
36 | }
37 |
38 | public void setDownloadUrl(String downloadUrl) {
39 | this.downloadUrl = downloadUrl;
40 | }
41 |
42 | public String getDescription() {
43 | return description;
44 | }
45 |
46 | public void setDescription(String description) {
47 | this.description = description;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/auth/AuthApi.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.auth;
2 |
3 | import io.reactivex.Observable;
4 | import pro.glideim.sdk.api.Response;
5 | import pro.glideim.sdk.http.RetrofitManager;
6 | import retrofit2.http.Body;
7 | import retrofit2.http.POST;
8 |
9 | public interface AuthApi {
10 |
11 | AuthApi API = RetrofitManager.create(AuthApi.class);
12 |
13 | @POST("auth/register")
14 | Observable> register(@Body RegisterDto d);
15 |
16 | @POST("auth/signin")
17 | Observable> login(@Body LoginDto d);
18 |
19 | @POST("auth/logout")
20 | Observable> logout();
21 |
22 | @POST("auth/token")
23 | Observable> auth(@Body AuthDto d);
24 | }
25 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/auth/AuthBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.auth;
2 |
3 | import java.util.List;
4 |
5 | public class AuthBean {
6 | private String token;
7 | private int uid;
8 | private List servers;
9 |
10 | public List getServers() {
11 | return servers;
12 | }
13 |
14 | public void setServers(List servers) {
15 | this.servers = servers;
16 | }
17 |
18 | public String getToken() {
19 | return token;
20 | }
21 |
22 | public void setToken(String token) {
23 | this.token = token;
24 | }
25 |
26 | public int getUid() {
27 | return uid;
28 | }
29 |
30 | public void setUid(int uid) {
31 | this.uid = uid;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/auth/AuthDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.auth;
2 |
3 | public class AuthDto {
4 | private String token;
5 | private int device;
6 |
7 | public AuthDto(String token, int device) {
8 | this.token = token;
9 | this.device = device;
10 | }
11 |
12 | public String getToken() {
13 | return token;
14 | }
15 |
16 | public void setToken(String token) {
17 | this.token = token;
18 | }
19 |
20 | public int getDevice() {
21 | return device;
22 | }
23 |
24 | public void setDevice(int device) {
25 | this.device = device;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/auth/LoginDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.auth;
2 |
3 | public class LoginDto {
4 | private String account;
5 | private String password;
6 | private int device;
7 |
8 | public LoginDto(String account, String password, int device) {
9 | this.account = account;
10 | this.password = password;
11 | this.device = device;
12 | }
13 |
14 | public String getAccount() {
15 | return account;
16 | }
17 |
18 | public void setAccount(String account) {
19 | this.account = account;
20 | }
21 |
22 | public String getPassword() {
23 | return password;
24 | }
25 |
26 | public void setPassword(String password) {
27 | this.password = password;
28 | }
29 |
30 | public int getDevice() {
31 | return device;
32 | }
33 |
34 | public void setDevice(int device) {
35 | this.device = device;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/auth/RegisterDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.auth;
2 |
3 | public class RegisterDto {
4 | private String account;
5 | private String password;
6 |
7 | public RegisterDto(String account, String password) {
8 | this.account = account;
9 | this.password = password;
10 | }
11 |
12 | public String getAccount() {
13 | return account;
14 | }
15 |
16 | public void setAccount(String account) {
17 | this.account = account;
18 | }
19 |
20 | public String getPassword() {
21 | return password;
22 | }
23 |
24 | public void setPassword(String password) {
25 | this.password = password;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/AddGroupMemberDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | import java.util.List;
4 |
5 | public class AddGroupMemberDto {
6 | private long gid;
7 | private List uid;
8 |
9 | public AddGroupMemberDto(long gid, List uid) {
10 | this.gid = gid;
11 | this.uid = uid;
12 | }
13 |
14 | public long getGid() {
15 | return gid;
16 | }
17 |
18 | public void setGid(long gid) {
19 | this.gid = gid;
20 | }
21 |
22 | public List getUid() {
23 | return uid;
24 | }
25 |
26 | public void setUid(List uid) {
27 | this.uid = uid;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/CreateGroupBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class CreateGroupBean {
4 | private long gid;
5 |
6 | public long getGid() {
7 | return gid;
8 | }
9 |
10 | public void setGid(long gid) {
11 | this.gid = gid;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/CreateGroupDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class CreateGroupDto {
4 | private String name;
5 |
6 | public CreateGroupDto(String name) {
7 | this.name = name;
8 | }
9 |
10 | public String getName() {
11 | return name;
12 | }
13 |
14 | public void setName(String name) {
15 | this.name = name;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/GetGroupInfoDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | import java.util.List;
4 |
5 | public class GetGroupInfoDto {
6 | private List gid;
7 |
8 | public GetGroupInfoDto(List gid) {
9 | this.gid = gid;
10 | }
11 |
12 | public List getGid() {
13 | return gid;
14 | }
15 |
16 | public void setGid(List gid) {
17 | this.gid = gid;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/GetGroupMemberDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class GetGroupMemberDto {
4 | private long gid;
5 |
6 | public GetGroupMemberDto(long gid) {
7 | this.gid = gid;
8 | }
9 |
10 | public long getGid() {
11 | return gid;
12 | }
13 |
14 | public void setGid(long gid) {
15 | this.gid = gid;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/GroupApi.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | import java.util.List;
4 |
5 | import io.reactivex.Observable;
6 | import pro.glideim.sdk.api.Response;
7 | import pro.glideim.sdk.http.RetrofitManager;
8 | import retrofit2.http.Body;
9 | import retrofit2.http.POST;
10 |
11 | public interface GroupApi {
12 |
13 | GroupApi API = RetrofitManager.create(GroupApi.class);
14 |
15 | @POST("group/info")
16 | Observable>> getGroupInfo(@Body GetGroupInfoDto d);
17 |
18 | @POST("group/members")
19 | Observable>> getGroupMember(@Body GetGroupMemberDto d);
20 |
21 | @POST("group/members/invite")
22 | Observable> inviteMember(@Body AddGroupMemberDto d);
23 |
24 | @POST("group/members/remove")
25 | Observable> removeMember(@Body RemoveMemberDto d);
26 |
27 | @POST("group/create")
28 | Observable> createGroup(@Body CreateGroupDto d);
29 |
30 | @POST("group/join")
31 | Observable> joinGroup(@Body JoinGroupDto d);
32 | }
33 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/GroupInfoBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class GroupInfoBean {
4 | private String name;
5 | private Long gid;
6 | private String avatar;
7 |
8 | public String getName() {
9 | return name;
10 | }
11 |
12 | public void setName(String name) {
13 | this.name = name;
14 | }
15 |
16 | public Long getGid() {
17 | return gid;
18 | }
19 |
20 | public void setGid(Long gid) {
21 | this.gid = gid;
22 | }
23 |
24 | public String getAvatar() {
25 | return avatar;
26 | }
27 |
28 | public void setAvatar(String avatar) {
29 | this.avatar = avatar;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/GroupMemberBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class GroupMemberBean {
4 | private long uid;
5 | private int type;
6 | private String remarkName;
7 |
8 | public long getUid() {
9 | return uid;
10 | }
11 |
12 | public void setUid(long uid) {
13 | this.uid = uid;
14 | }
15 |
16 | public int getType() {
17 | return type;
18 | }
19 |
20 | public void setType(int type) {
21 | this.type = type;
22 | }
23 |
24 | public String getRemarkName() {
25 | return remarkName;
26 | }
27 |
28 | public void setRemarkName(String remarkName) {
29 | this.remarkName = remarkName;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/JoinGroupDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | public class JoinGroupDto {
4 | private Long gid;
5 |
6 | public JoinGroupDto(Long gid) {
7 | this.gid = gid;
8 | }
9 |
10 | public Long getGid() {
11 | return gid;
12 | }
13 |
14 | public void setGid(Long gid) {
15 | this.gid = gid;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/group/RemoveMemberDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.group;
2 |
3 | import java.util.List;
4 |
5 | public class RemoveMemberDto {
6 | private long gid;
7 | private List uid;
8 |
9 | public RemoveMemberDto(long gid, List uid) {
10 | this.gid = gid;
11 | this.uid = uid;
12 | }
13 |
14 | public long getGid() {
15 | return gid;
16 | }
17 |
18 | public void setGid(long gid) {
19 | this.gid = gid;
20 | }
21 |
22 | public List getUid() {
23 | return uid;
24 | }
25 |
26 | public void setUid(List uid) {
27 | this.uid = uid;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/AckOfflineMsgDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | import java.util.List;
4 |
5 | public class AckOfflineMsgDto {
6 | private List mid;
7 |
8 | public AckOfflineMsgDto(List mid) {
9 | this.mid = mid;
10 | }
11 |
12 | public List getMid() {
13 | return mid;
14 | }
15 |
16 | public void setMid(List mid) {
17 | this.mid = mid;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GetChatHistoryDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GetChatHistoryDto {
4 | private long uid;
5 | private long beforeMid;
6 |
7 | public GetChatHistoryDto(long uid, long beforeMid) {
8 | this.uid = uid;
9 | this.beforeMid = beforeMid;
10 | }
11 |
12 | public long getUid() {
13 | return uid;
14 | }
15 |
16 | public void setUid(long uid) {
17 | this.uid = uid;
18 | }
19 |
20 | public long getBeforeMid() {
21 | return beforeMid;
22 | }
23 |
24 | public void setBeforeMid(long beforeMid) {
25 | this.beforeMid = beforeMid;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GetGroupMessageStateDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GetGroupMessageStateDto {
4 | private Long gid;
5 |
6 |
7 | public GetGroupMessageStateDto(Long gid) {
8 | this.gid = gid;
9 | }
10 |
11 | public Long getGid() {
12 | return gid;
13 | }
14 |
15 | public void setGid(Long gid) {
16 | this.gid = gid;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GetGroupMsgHistoryDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GetGroupMsgHistoryDto {
4 | private long gid;
5 | private long beforeSeq;
6 |
7 | public GetGroupMsgHistoryDto(long gid) {
8 | this.gid = gid;
9 | }
10 |
11 | public GetGroupMsgHistoryDto(long gid, long beforeSeq) {
12 | this.gid = gid;
13 | this.beforeSeq = beforeSeq;
14 | }
15 |
16 | public long getGid() {
17 | return gid;
18 | }
19 |
20 | public void setGid(long gid) {
21 | this.gid = gid;
22 | }
23 |
24 | public long getBeforeSeq() {
25 | return beforeSeq;
26 | }
27 |
28 | public void setBeforeSeq(long beforeSeq) {
29 | this.beforeSeq = beforeSeq;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GetSessionDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GetSessionDto {
4 | private long to;
5 |
6 | public GetSessionDto(long to) {
7 | this.to = to;
8 | }
9 |
10 | public long getTo() {
11 | return to;
12 | }
13 |
14 | public void setTo(long to) {
15 | this.to = to;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GetUserMsgDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | import java.util.List;
4 |
5 | public class GetUserMsgDto {
6 | private List uid;
7 |
8 | public GetUserMsgDto(List uid) {
9 | this.uid = uid;
10 | }
11 |
12 | public List getUid() {
13 | return uid;
14 | }
15 |
16 | public void setUid(List uid) {
17 | this.uid = uid;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GroupMessageBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GroupMessageBean {
4 |
5 | private long mid;
6 | private long sender;
7 | private long gid;
8 | private int type;
9 | private long seq;
10 | private long sendAt;
11 | private String content;
12 | private int status;
13 | private long recallBy;
14 |
15 | public long getRecallBy() {
16 | return recallBy;
17 | }
18 |
19 | public void setRecallBy(long recallBy) {
20 | this.recallBy = recallBy;
21 | }
22 |
23 | public int getStatus() {
24 | return status;
25 | }
26 |
27 | public void setStatus(int status) {
28 | this.status = status;
29 | }
30 |
31 | public long getSeq() {
32 | return seq;
33 | }
34 |
35 | public void setSeq(long seq) {
36 | this.seq = seq;
37 | }
38 |
39 | public long getMid() {
40 | return mid;
41 | }
42 |
43 | public void setMid(long mid) {
44 | this.mid = mid;
45 | }
46 |
47 | public long getSender() {
48 | return sender;
49 | }
50 |
51 | public void setSender(long sender) {
52 | this.sender = sender;
53 | }
54 |
55 | public long getGid() {
56 | return gid;
57 | }
58 |
59 | public void setGid(long gid) {
60 | this.gid = gid;
61 | }
62 |
63 | public int getType() {
64 | return type;
65 | }
66 |
67 | public void setType(int type) {
68 | this.type = type;
69 | }
70 |
71 | public long getSendAt() {
72 | return sendAt;
73 | }
74 |
75 | public void setSendAt(long sendAt) {
76 | this.sendAt = sendAt;
77 | }
78 |
79 | public String getContent() {
80 | return content;
81 | }
82 |
83 | public void setContent(String content) {
84 | this.content = content;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/GroupMessageStateBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class GroupMessageStateBean {
4 | private Long gid;
5 | private long lastMID;
6 | private long lastSeq;
7 | private long lastMsgAt;
8 |
9 | public Long getGid() {
10 | return gid;
11 | }
12 |
13 | public void setGid(Long gid) {
14 | this.gid = gid;
15 | }
16 |
17 | public long getLastMID() {
18 | return lastMID;
19 | }
20 |
21 | public void setLastMID(long lastMID) {
22 | this.lastMID = lastMID;
23 | }
24 |
25 | public long getLastSeq() {
26 | return lastSeq;
27 | }
28 |
29 | public void setLastSeq(long lastSeq) {
30 | this.lastSeq = lastSeq;
31 | }
32 |
33 | public long getLastMsgAt() {
34 | return lastMsgAt;
35 | }
36 |
37 | public void setLastMsgAt(long lastMsgAt) {
38 | this.lastMsgAt = lastMsgAt;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/MessageBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class MessageBean {
4 | private long mid;
5 | private long cliSeq;
6 | private long from;
7 | private long to;
8 | private int type;
9 | private long sendAt;
10 | private long createAt;
11 | private String content;
12 | private int status;
13 |
14 | public int getStatus() {
15 | return status;
16 | }
17 |
18 | public void setStatus(int status) {
19 | this.status = status;
20 | }
21 |
22 | public long getMid() {
23 | return mid;
24 | }
25 |
26 | public void setMid(long mid) {
27 | this.mid = mid;
28 | }
29 |
30 | public long getCliSeq() {
31 | return cliSeq;
32 | }
33 |
34 | public void setCliSeq(long cliSeq) {
35 | this.cliSeq = cliSeq;
36 | }
37 |
38 | public long getFrom() {
39 | return from;
40 | }
41 |
42 | public void setFrom(long from) {
43 | this.from = from;
44 | }
45 |
46 | public long getTo() {
47 | return to;
48 | }
49 |
50 | public void setTo(long to) {
51 | this.to = to;
52 | }
53 |
54 | public int getType() {
55 | return type;
56 | }
57 |
58 | public void setType(int type) {
59 | this.type = type;
60 | }
61 |
62 | public long getSendAt() {
63 | return sendAt;
64 | }
65 |
66 | public void setSendAt(long sendAt) {
67 | this.sendAt = sendAt;
68 | }
69 |
70 | public long getCreateAt() {
71 | return createAt;
72 | }
73 |
74 | public void setCreateAt(long createAt) {
75 | this.createAt = createAt;
76 | }
77 |
78 | public String getContent() {
79 | return content;
80 | }
81 |
82 | public void setContent(String content) {
83 | this.content = content;
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/MessageIDBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class MessageIDBean {
4 | private long mid;
5 |
6 | public long getMid() {
7 | return mid;
8 | }
9 |
10 | public void setMid(long mid) {
11 | this.mid = mid;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/MsgApi.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | import java.util.List;
4 |
5 | import io.reactivex.Observable;
6 | import pro.glideim.sdk.api.Response;
7 | import pro.glideim.sdk.http.RetrofitManager;
8 | import retrofit2.http.Body;
9 | import retrofit2.http.POST;
10 |
11 | public interface MsgApi {
12 |
13 | MsgApi API = RetrofitManager.create(MsgApi.class);
14 |
15 | @POST("msg/id")
16 | Observable> getMessageID();
17 |
18 | @POST("msg/chat/recent")
19 | Observable>> getRecentChatMessage();
20 |
21 | @POST("msg/chat/user")
22 | Observable>> getChatMessageByUsers(@Body GetUserMsgDto d);
23 |
24 | @POST("msg/chat/history")
25 | Observable>> getChatMessageHistory(@Body GetChatHistoryDto d);
26 |
27 | @POST("msg/group/recent")
28 | Observable>> getRecentGroupMessage(@Body GetGroupMsgHistoryDto d);
29 |
30 | @POST("msg/group/history")
31 | Observable>> getGroupMessageHistory(@Body GetGroupMsgHistoryDto d);
32 |
33 | @POST("msg/group/state")
34 | Observable> getGroupMessageState(@Body GetGroupMessageStateDto d);
35 |
36 | @POST("msg/group/state/all")
37 | Observable>> getAllGroupMessageState();
38 |
39 | @POST("msg/chat/offline")
40 | Observable>> getOfflineMsg();
41 |
42 | @POST("msg/chat/offline/ack")
43 | Observable> ackOfflineMsg(@Body AckOfflineMsgDto d);
44 |
45 | @POST("session/recent")
46 | Observable>> getRecentSession();
47 |
48 | @POST("session/get")
49 | Observable> getSession(@Body GetSessionDto d);
50 |
51 | @POST("session/update")
52 | Observable> updateSession(@Body GetSessionDto d);
53 | }
54 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/SessionBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | public class SessionBean {
4 | private long uid1;
5 | private long uid2;
6 | private long lastMid;
7 | private long updateAt;
8 | private long createAt;
9 |
10 | public long getCreateAt() {
11 | return createAt;
12 | }
13 |
14 | public void setCreateAt(long createAt) {
15 | this.createAt = createAt;
16 | }
17 |
18 | public long getUid1() {
19 | return uid1;
20 | }
21 |
22 | public void setUid1(long uid1) {
23 | this.uid1 = uid1;
24 | }
25 |
26 | public long getUid2() {
27 | return uid2;
28 | }
29 |
30 | public void setUid2(long uid2) {
31 | this.uid2 = uid2;
32 | }
33 |
34 | public long getLastMid() {
35 | return lastMid;
36 | }
37 |
38 | public void setLastMid(long lastMid) {
39 | this.lastMid = lastMid;
40 | }
41 |
42 | public long getUpdateAt() {
43 | return updateAt;
44 | }
45 |
46 | public void setUpdateAt(long updateAt) {
47 | this.updateAt = updateAt;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/msg/UserMsgBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.msg;
2 |
3 | import java.util.List;
4 |
5 | public class UserMsgBean {
6 | private long uid;
7 | private List messages;
8 |
9 | public long getUid() {
10 | return uid;
11 | }
12 |
13 | public void setUid(long uid) {
14 | this.uid = uid;
15 | }
16 |
17 | public List getMessages() {
18 | return messages;
19 | }
20 |
21 | public void setMessages(List messages) {
22 | this.messages = messages;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/ApprovalContactsDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class ApprovalContactsDto {
4 | private long uid;
5 | private boolean agree;
6 | private boolean deny;
7 | private String comment;
8 |
9 | public ApprovalContactsDto(long uid, boolean agree, boolean deny, String comment) {
10 | this.uid = uid;
11 | this.agree = agree;
12 | this.deny = deny;
13 | this.comment = comment;
14 | }
15 |
16 | public long getUid() {
17 | return uid;
18 | }
19 |
20 | public void setUid(long uid) {
21 | this.uid = uid;
22 | }
23 |
24 | public boolean isAgree() {
25 | return agree;
26 | }
27 |
28 | public void setAgree(boolean agree) {
29 | this.agree = agree;
30 | }
31 |
32 | public boolean isDeny() {
33 | return deny;
34 | }
35 |
36 | public void setDeny(boolean deny) {
37 | this.deny = deny;
38 | }
39 |
40 | public String getComment() {
41 | return comment;
42 | }
43 |
44 | public void setComment(String comment) {
45 | this.comment = comment;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/ContactsBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class ContactsBean {
4 | private long id;
5 | private int type;
6 | private String remark;
7 |
8 | public long getId() {
9 | return id;
10 | }
11 |
12 | public void setId(long id) {
13 | this.id = id;
14 | }
15 |
16 | public int getType() {
17 | return type;
18 | }
19 |
20 | public void setType(int type) {
21 | this.type = type;
22 | }
23 |
24 | public String getRemark() {
25 | return remark;
26 | }
27 |
28 | public void setRemark(String remark) {
29 | this.remark = remark;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/ContactsUidDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class ContactsUidDto {
4 | private long uid;
5 | private String remark;
6 |
7 | public ContactsUidDto(long uid, String remark) {
8 | this.uid = uid;
9 | this.remark = remark;
10 | }
11 |
12 | public long getUid() {
13 | return uid;
14 | }
15 |
16 | public void setUid(long uid) {
17 | this.uid = uid;
18 | }
19 |
20 | public String getRemark() {
21 | return remark;
22 | }
23 |
24 | public void setRemark(String remark) {
25 | this.remark = remark;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/GetUserInfoDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | import java.util.List;
4 |
5 | public class GetUserInfoDto {
6 | private List uid;
7 |
8 | public GetUserInfoDto(List uid) {
9 | this.uid = uid;
10 | }
11 |
12 | public List getUid() {
13 | return uid;
14 | }
15 |
16 | public void setUid(List uid) {
17 | this.uid = uid;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/ProfileBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class ProfileBean {
4 | private long uid;
5 | private String account;
6 | private String nickname;
7 | private String avatar;
8 |
9 | public long getUid() {
10 | return uid;
11 | }
12 |
13 | public void setUid(long uid) {
14 | this.uid = uid;
15 | }
16 |
17 | public String getAccount() {
18 | return account;
19 | }
20 |
21 | public void setAccount(String account) {
22 | this.account = account;
23 | }
24 |
25 | public String getNickname() {
26 | return nickname;
27 | }
28 |
29 | public void setNickname(String nickname) {
30 | this.nickname = nickname;
31 | }
32 |
33 | public String getAvatar() {
34 | return avatar;
35 | }
36 |
37 | public void setAvatar(String avatar) {
38 | this.avatar = avatar;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/RegisterDto.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class RegisterDto {
4 | private String account;
5 | private String password;
6 |
7 | public RegisterDto(String account, String password) {
8 | this.account = account;
9 | this.password = password;
10 | }
11 |
12 | public String getAccount() {
13 | return account;
14 | }
15 |
16 | public void setAccount(String account) {
17 | this.account = account;
18 | }
19 |
20 | public String getPassword() {
21 | return password;
22 | }
23 |
24 | public void setPassword(String password) {
25 | this.password = password;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/TokenBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class TokenBean {
4 | private String token;
5 | private int uid;
6 |
7 | public int getUid() {
8 | return uid;
9 | }
10 |
11 | public void setUid(int uid) {
12 | this.uid = uid;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/UserApi.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | import io.reactivex.Observable;
4 | import pro.glideim.sdk.api.Response;
5 | import pro.glideim.sdk.http.RetrofitManager;
6 | import retrofit2.http.Body;
7 | import retrofit2.http.POST;
8 |
9 | import java.util.List;
10 |
11 | public interface UserApi {
12 |
13 | UserApi API = RetrofitManager.create(UserApi.class);
14 |
15 | @POST("contacts/list")
16 | Observable>> getContactsList();
17 |
18 | @POST("contacts/add")
19 | Observable> addContacts(@Body ContactsUidDto d);
20 |
21 | @POST("contacts/del")
22 | Observable> delContacts(@Body ContactsUidDto d);
23 |
24 | @POST("contacts/approval")
25 | Observable> contactsApproval(@Body ApprovalContactsDto d);
26 |
27 | @POST("user/info")
28 | Observable>> getUserInfo(@Body GetUserInfoDto d);
29 |
30 | @POST("user/profile")
31 | Observable> myProfile();
32 |
33 | @POST("user/profile/update")
34 | Observable> updateMyProfile();
35 | }
36 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/api/user/UserInfoBean.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.api.user;
2 |
3 | public class UserInfoBean {
4 | private long uid;
5 | private String nickname;
6 | private String account;
7 | private String avatar;
8 |
9 | public long getUid() {
10 | return uid;
11 | }
12 |
13 | public void setUid(long uid) {
14 | this.uid = uid;
15 | }
16 |
17 | public String getNickname() {
18 | return nickname;
19 | }
20 |
21 | public void setNickname(String nickname) {
22 | this.nickname = nickname;
23 | }
24 |
25 | public String getAccount() {
26 | return account;
27 | }
28 |
29 | public void setAccount(String account) {
30 | this.account = account;
31 | }
32 |
33 | public String getAvatar() {
34 | return avatar;
35 | }
36 |
37 | public void setAvatar(String avatar) {
38 | this.avatar = avatar;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/http/AuthInterceptor.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.http;
2 |
3 | import java.io.IOException;
4 | import java.net.ConnectException;
5 |
6 | import okhttp3.Interceptor;
7 | import okhttp3.Request;
8 | import okhttp3.Response;
9 | import pro.glideim.sdk.GlideIM;
10 |
11 | public class AuthInterceptor implements Interceptor {
12 |
13 | private static final AuthInterceptor instance = new AuthInterceptor();
14 |
15 | public static AuthInterceptor create() {
16 | return instance;
17 | }
18 |
19 | @Override
20 | public Response intercept(Chain chain) throws IOException {
21 | Request.Builder request = chain.request().newBuilder();
22 |
23 | String jwtToken = GlideIM.getDataStorage().loadToken(GlideIM.getAccount().uid);
24 | request.addHeader("Authorization", "Bearer " + jwtToken);
25 | return chain.proceed(request.build());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/im/ConnStateListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.im;
2 |
3 | public interface ConnStateListener {
4 | void onStateChange(int state, String msg);
5 | }
6 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/im/Heartbeat.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.im;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | import io.reactivex.Observable;
6 | import io.reactivex.disposables.Disposable;
7 | import pro.glideim.sdk.messages.Actions;
8 | import pro.glideim.sdk.messages.CommMessage;
9 | import pro.glideim.sdk.utils.SLogger;
10 | import pro.glideim.sdk.ws.WsClient;
11 |
12 | public class Heartbeat implements ConnStateListener {
13 |
14 | private static final String TAG = Heartbeat.class.getSimpleName();
15 | private final pro.glideim.sdk.im.IMClient client;
16 | private Disposable disposable;
17 |
18 | private Heartbeat(pro.glideim.sdk.im.IMClient client) {
19 | this.client = client;
20 | this.client.getWebSocketClient().addStateListener(this);
21 | }
22 |
23 | public static Heartbeat start(pro.glideim.sdk.im.IMClient client) {
24 | Heartbeat heartbeat = new Heartbeat(client);
25 | heartbeat.start();
26 | return heartbeat;
27 | }
28 |
29 | @Override
30 | public void onStateChange(int state, String msg) {
31 | if (state == WsClient.STATE_OPENED) {
32 | start();
33 | } else if (state == WsClient.STATE_CLOSED) {
34 | stop();
35 | }
36 | }
37 |
38 | public void start() {
39 | stop();
40 | SLogger.d(TAG, "start");
41 | Observable.interval(3, TimeUnit.SECONDS)
42 | .doOnSubscribe(disposable -> {
43 | stop();
44 | this.disposable = disposable;
45 | })
46 | .doOnNext(aLong -> {
47 | if (client.isConnected()) {
48 | client.send(new CommMessage<>(1, Actions.ACTION_HEARTBEAT, 0, ""));
49 | } else {
50 | stop();
51 | }
52 | })
53 | .subscribe();
54 | }
55 |
56 | public boolean isRunning() {
57 | return disposable.isDisposed();
58 | }
59 |
60 | public void stop() {
61 | if (disposable != null && !disposable.isDisposed()) {
62 | disposable.dispose();
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/im/IMClient.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.im;
2 |
3 | import io.reactivex.Observable;
4 | import io.reactivex.Single;
5 | import pro.glideim.sdk.messages.ChatMessage;
6 | import pro.glideim.sdk.messages.CommMessage;
7 | import pro.glideim.sdk.ws.WsClient;
8 |
9 | public interface IMClient {
10 | void addConnStateListener(ConnStateListener connStateListener);
11 |
12 | void removeConnStateListener(ConnStateListener connStateListener);
13 |
14 | void setMessageListener(MessageListener listener);
15 |
16 | Single connect();
17 |
18 | boolean isConnected();
19 |
20 | Observable sendChatMessage(ChatMessage m);
21 |
22 | Observable sendMessage(String action, ChatMessage m);
23 |
24 | Observable sendGroupMessage(ChatMessage m);
25 |
26 | Observable> request(String action, Class clazz, boolean isArray, Object data);
27 |
28 | void disconnect();
29 |
30 | boolean send(Object obj);
31 |
32 | WsClient getWebSocketClient();
33 | }
34 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/im/Message.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.im;
2 |
3 | public class Message {
4 | String message;
5 |
6 | public Message(String message) {
7 | this.message = message;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/glide-im-sdk/src/main/java/pro/glideim/sdk/im/MessageListener.java:
--------------------------------------------------------------------------------
1 | package pro.glideim.sdk.im;
2 |
3 | import pro.glideim.sdk.messages.ChatMessage;
4 | import pro.glideim.sdk.messages.CommMessage;
5 | import pro.glideim.sdk.messages.GroupMessage;
6 |
7 | public interface MessageListener {
8 | void onNewMessage(ChatMessage m);
9 | void onGroupMessage(GroupMessage m);
10 | void onControlMessage(CommMessage