Skip to content

Commit f75d061

Browse files
committed
Update tutorial code to use Chat v7
1 parent 467c333 commit f75d061

27 files changed

Lines changed: 279 additions & 236 deletions

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ buildscript {
55
}
66
dependencies {
77
classpath 'com.android.tools.build:gradle:8.13.1'
8-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.21"
8+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.0"
99
}
1010
}
1111

samplejava/build.gradle

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ plugins {
33
}
44

55
android {
6-
compileSdk 35
6+
compileSdk 36
77
namespace "com.example.chattutorial"
88

99
defaultConfig {
1010
applicationId "com.example.chattutorial"
11-
minSdk 21
12-
targetSdk 34
11+
minSdk 24
12+
targetSdk 36
1313
versionCode 1
1414
versionName "1.0"
1515

@@ -27,14 +27,18 @@ android {
2727
buildFeatures {
2828
viewBinding true
2929
}
30+
31+
compileOptions {
32+
sourceCompatibility = JavaVersion.VERSION_11
33+
targetCompatibility = JavaVersion.VERSION_11
34+
}
3035
}
3136

3237
dependencies {
33-
// Add new dependencies
34-
implementation "io.getstream:stream-chat-android-ui-components:6.28.0"
35-
implementation "io.getstream:stream-chat-android-offline:6.28.0"
38+
// Add the dependency
39+
implementation "io.getstream:stream-chat-android-ui-components:7.3.0"
3640
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7"
3741
implementation "com.google.android.material:material:1.12.0"
3842
implementation "androidx.activity:activity-ktx:1.10.1"
39-
implementation "io.coil-kt:coil:2.7.0"
43+
implementation "io.coil-kt.coil3:coil:3.1.0"
4044
}

samplejava/src/main/java/com/example/chattutorial/ChannelActivity.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
import io.getstream.chat.android.models.Message;
1616
import io.getstream.chat.android.ui.common.state.messages.Edit;
1717
import io.getstream.chat.android.ui.common.state.messages.MessageMode;
18-
import io.getstream.chat.android.ui.feature.messages.header.MessageListHeaderView;
18+
import io.getstream.chat.android.ui.feature.messages.header.ChannelHeaderView;
1919
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModel;
2020
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModelBinding;
21-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModel;
22-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModelBinding;
21+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModel;
22+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModelBinding;
2323
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModel;
2424
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelBinding;
25-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelFactory;
25+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelViewModelFactory;
2626

2727
public class ChannelActivity extends AppCompatActivity {
2828

@@ -38,59 +38,61 @@ public static Intent newIntent(Context context, Channel channel) {
3838
protected void onCreate(@Nullable Bundle savedInstanceState) {
3939
super.onCreate(savedInstanceState);
4040

41-
// Step 0 - inflate binding
41+
// inflate binding
4242
ActivityChannelBinding binding = ActivityChannelBinding.inflate(getLayoutInflater());
4343
setContentView(binding.getRoot());
4444

45+
EdgeToEdge.applySystemBarInsetsAsPadding(binding.getRoot());
46+
4547
String cid = getIntent().getStringExtra(CID_KEY);
4648
if (cid == null) {
4749
throw new IllegalStateException("Specifying a channel id is required when starting ChannelActivity");
4850
}
4951

50-
// Step 1 - Create three separate ViewModels for the views so it's easy
51-
// to customize them individually
52-
ViewModelProvider.Factory factory = new MessageListViewModelFactory.Builder(this)
52+
// Create three separate ViewModels for the views so it's easy
53+
// to customize them individually
54+
ViewModelProvider.Factory factory = new ChannelViewModelFactory.Builder(this)
5355
.cid(cid)
5456
.build();
5557
ViewModelProvider provider = new ViewModelProvider(this, factory);
56-
MessageListHeaderViewModel messageListHeaderViewModel = provider.get(MessageListHeaderViewModel.class);
58+
ChannelHeaderViewModel channelHeaderViewModel = provider.get(ChannelHeaderViewModel.class);
5759
MessageListViewModel messageListViewModel = provider.get(MessageListViewModel.class);
5860
MessageComposerViewModel messageComposerViewModel = provider.get(MessageComposerViewModel.class);
5961

6062
// TODO set custom Imgur attachment factory
6163

62-
// Step 2 - Bind the view and ViewModels, they are loosely coupled so it's easy to customize
63-
MessageListHeaderViewModelBinding.bind(messageListHeaderViewModel, binding.messageListHeaderView, this);
64+
// Bind the view and ViewModels, they are loosely coupled so it's easy to customize
65+
ChannelHeaderViewModelBinding.bind(channelHeaderViewModel, binding.channelHeaderView, this);
6466
MessageListViewModelBinding.bind(messageListViewModel, binding.messageListView, this);
6567
MessageComposerViewModelBinding.bind(messageComposerViewModel, binding.messageComposerView, this);
6668

67-
// Step 3 - Let both MessageListHeaderView and MessageComposerView know when we open a thread
69+
// Let both ChannelHeaderView and MessageComposerView know when we open a thread
6870
messageListViewModel.getMode().observe(this, mode -> {
6971
if (mode instanceof MessageMode.MessageThread) {
7072
Message parentMessage = ((MessageMode.MessageThread) mode).getParentMessage();
71-
messageListHeaderViewModel.setActiveThread(parentMessage);
73+
channelHeaderViewModel.setActiveThread(parentMessage);
7274
messageComposerViewModel.setMessageMode(new MessageMode.MessageThread(parentMessage));
7375
} else if (mode instanceof MessageMode.Normal) {
74-
messageListHeaderViewModel.resetThread();
76+
channelHeaderViewModel.resetThread();
7577
messageComposerViewModel.leaveThread();
7678
}
7779
});
7880

79-
// Step 4 - Let the message input know when we are editing a message
81+
// Let the message input know when we are editing a message
8082
binding.messageListView.setMessageEditHandler(message -> {
8183
messageComposerViewModel.performMessageAction(new Edit(message));
8284
});
8385

84-
// Step 5 - Handle navigate up state
86+
// Handle navigate up state
8587
messageListViewModel.getState().observe(this, state -> {
8688
if (state instanceof MessageListViewModel.State.NavigateUp) {
8789
finish();
8890
}
8991
});
9092

91-
// Step 6 - Handle back button behaviour correctly when you're in a thread
92-
MessageListHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
93-
binding.messageListHeaderView.setBackButtonClickListener(backHandler);
93+
// Handle back button behaviour correctly when you're in a thread
94+
ChannelHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
95+
binding.channelHeaderView.setBackButtonClickListener(backHandler);
9496
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
9597
@Override
9698
public void handleOnBackPressed() {

samplejava/src/main/java/com/example/chattutorial/ChannelActivity2.java

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
import io.getstream.chat.android.models.Message;
1919
import io.getstream.chat.android.ui.common.state.messages.Edit;
2020
import io.getstream.chat.android.ui.common.state.messages.MessageMode;
21-
import io.getstream.chat.android.ui.feature.messages.header.MessageListHeaderView;
21+
import io.getstream.chat.android.ui.feature.messages.header.ChannelHeaderView;
2222
import io.getstream.chat.android.ui.feature.messages.list.adapter.viewholder.attachment.AttachmentFactoryManager;
2323
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModel;
2424
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModelBinding;
25-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModel;
26-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModelBinding;
25+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModel;
26+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModelBinding;
2727
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModel;
2828
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelBinding;
29-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelFactory;
29+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelViewModelFactory;
3030

3131
public class ChannelActivity2 extends AppCompatActivity {
3232

@@ -42,22 +42,24 @@ public static Intent newIntent(Context context, Channel channel) {
4242
protected void onCreate(@Nullable Bundle savedInstanceState) {
4343
super.onCreate(savedInstanceState);
4444

45-
// Step 0 - inflate binding
45+
// inflate binding
4646
ActivityChannel2Binding binding = ActivityChannel2Binding.inflate(getLayoutInflater());
4747
setContentView(binding.getRoot());
4848

49+
EdgeToEdge.applySystemBarInsetsAsPadding(binding.getRoot());
50+
4951
String cid = getIntent().getStringExtra(CID_KEY);
5052
if (cid == null) {
5153
throw new IllegalStateException("Specifying a channel id is required when starting ChannelActivity2");
5254
}
5355

54-
// Step 1 - Create three separate ViewModels for the views so it's easy
55-
// to customize them individually
56-
ViewModelProvider.Factory factory = new MessageListViewModelFactory.Builder(this)
56+
// Create three separate ViewModels for the views so it's easy
57+
// to customize them individually
58+
ViewModelProvider.Factory factory = new ChannelViewModelFactory.Builder(this)
5759
.cid(cid)
5860
.build();
5961
ViewModelProvider provider = new ViewModelProvider(this, factory);
60-
MessageListHeaderViewModel messageListHeaderViewModel = provider.get(MessageListHeaderViewModel.class);
62+
ChannelHeaderViewModel channelHeaderViewModel = provider.get(ChannelHeaderViewModel.class);
6163
MessageListViewModel messageListViewModel = provider.get(MessageListViewModel.class);
6264
MessageComposerViewModel messageComposerViewModel = provider.get(MessageComposerViewModel.class);
6365

@@ -70,38 +72,38 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
7072
AttachmentFactoryManager attachmentFactoryManager = new AttachmentFactoryManager(imgurAttachmentViewFactories);
7173
binding.messageListView.setAttachmentFactoryManager(attachmentFactoryManager);
7274

73-
// Step 2 - Bind the view and ViewModels, they are loosely coupled so it's easy to customize
74-
MessageListHeaderViewModelBinding.bind(messageListHeaderViewModel, binding.messageListHeaderView, this);
75+
// Bind the view and ViewModels, they are loosely coupled so it's easy to customize
76+
ChannelHeaderViewModelBinding.bind(channelHeaderViewModel, binding.channelHeaderView, this);
7577
MessageListViewModelBinding.bind(messageListViewModel, binding.messageListView, this);
7678
MessageComposerViewModelBinding.bind(messageComposerViewModel, binding.messageComposerView, this);
7779

78-
// Step 3 - Let both MessageListHeaderView and MessageComposerView know when we open a thread
80+
// Let both ChannelHeaderView and MessageComposerView know when we open a thread
7981
messageListViewModel.getMode().observe(this, mode -> {
8082
if (mode instanceof MessageMode.MessageThread) {
8183
Message parentMessage = ((MessageMode.MessageThread) mode).getParentMessage();
82-
messageListHeaderViewModel.setActiveThread(parentMessage);
84+
channelHeaderViewModel.setActiveThread(parentMessage);
8385
messageComposerViewModel.setMessageMode(new MessageMode.MessageThread(parentMessage));
8486
} else if (mode instanceof MessageMode.Normal) {
85-
messageListHeaderViewModel.resetThread();
87+
channelHeaderViewModel.resetThread();
8688
messageComposerViewModel.leaveThread();
8789
}
8890
});
8991

90-
// Step 4 - Let the message input know when we are editing a message
92+
// Let the message input know when we are editing a message
9193
binding.messageListView.setMessageEditHandler(message -> {
9294
messageComposerViewModel.performMessageAction(new Edit(message));
9395
});
9496

95-
// Step 5 - Handle navigate up state
97+
// Handle navigate up state
9698
messageListViewModel.getState().observe(this, state -> {
9799
if (state instanceof MessageListViewModel.State.NavigateUp) {
98100
finish();
99101
}
100102
});
101103

102-
// Step 6 - Handle back button behaviour correctly when you're in a thread
103-
MessageListHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
104-
binding.messageListHeaderView.setBackButtonClickListener(backHandler);
104+
// Handle back button behaviour correctly when you're in a thread
105+
ChannelHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
106+
binding.channelHeaderView.setBackButtonClickListener(backHandler);
105107
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
106108
@Override
107109
public void handleOnBackPressed() {

samplejava/src/main/java/com/example/chattutorial/ChannelActivity3.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@
2323
import io.getstream.chat.android.models.Channel;
2424
import io.getstream.chat.android.models.Message;
2525
import io.getstream.chat.android.models.TypingEvent;
26-
import io.getstream.chat.android.state.extensions.ChatClientExtensions;
26+
import io.getstream.chat.android.client.api.state.ChatClientExtensions;
2727
import io.getstream.chat.android.ui.common.state.messages.Edit;
2828
import io.getstream.chat.android.ui.common.state.messages.MessageMode;
29-
import io.getstream.chat.android.ui.feature.messages.header.MessageListHeaderView;
29+
import io.getstream.chat.android.ui.feature.messages.header.ChannelHeaderView;
3030
import io.getstream.chat.android.ui.feature.messages.list.adapter.viewholder.attachment.AttachmentFactoryManager;
3131
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModel;
3232
import io.getstream.chat.android.ui.viewmodel.messages.MessageComposerViewModelBinding;
33-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModel;
34-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListHeaderViewModelBinding;
33+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModel;
34+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelHeaderViewModelBinding;
3535
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModel;
3636
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelBinding;
37-
import io.getstream.chat.android.ui.viewmodel.messages.MessageListViewModelFactory;
37+
import io.getstream.chat.android.ui.viewmodel.messages.ChannelViewModelFactory;
3838
import kotlinx.coroutines.flow.Flow;
3939

4040
public class ChannelActivity3 extends AppCompatActivity {
@@ -51,22 +51,24 @@ public static Intent newIntent(Context context, Channel channel) {
5151
protected void onCreate(@Nullable Bundle savedInstanceState) {
5252
super.onCreate(savedInstanceState);
5353

54-
// Step 0 - inflate binding
54+
// inflate binding
5555
ActivityChannel3Binding binding = ActivityChannel3Binding.inflate(getLayoutInflater());
5656
setContentView(binding.getRoot());
5757

58+
EdgeToEdge.applySystemBarInsetsAsPadding(binding.getRoot());
59+
5860
String cid = getIntent().getStringExtra(CID_KEY);
5961
if (cid == null) {
6062
throw new IllegalStateException("Specifying a channel id is required when starting ChannelActivity3");
6163
}
6264

63-
// Step 1 - Create three separate ViewModels for the views so it's easy
64-
// to customize them individually
65-
ViewModelProvider.Factory factory = new MessageListViewModelFactory.Builder(this)
65+
// Create three separate ViewModels for the views so it's easy
66+
// to customize them individually
67+
ViewModelProvider.Factory factory = new ChannelViewModelFactory.Builder(this)
6668
.cid(cid)
6769
.build();
6870
ViewModelProvider provider = new ViewModelProvider(this, factory);
69-
MessageListHeaderViewModel messageListHeaderViewModel = provider.get(MessageListHeaderViewModel.class);
71+
ChannelHeaderViewModel channelHeaderViewModel = provider.get(ChannelHeaderViewModel.class);
7072
MessageListViewModel messageListViewModel = provider.get(MessageListViewModel.class);
7173
MessageComposerViewModel messageComposerViewModel = provider.get(MessageComposerViewModel.class);
7274

@@ -79,38 +81,38 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
7981
AttachmentFactoryManager attachmentFactoryManager = new AttachmentFactoryManager(imgurAttachmentViewFactories);
8082
binding.messageListView.setAttachmentFactoryManager(attachmentFactoryManager);
8183

82-
// Step 2 - Bind the view and ViewModels, they are loosely coupled so it's easy to customize
83-
MessageListHeaderViewModelBinding.bind(messageListHeaderViewModel, binding.messageListHeaderView, this);
84+
// Bind the view and ViewModels, they are loosely coupled so it's easy to customize
85+
ChannelHeaderViewModelBinding.bind(channelHeaderViewModel, binding.channelHeaderView, this);
8486
MessageListViewModelBinding.bind(messageListViewModel, binding.messageListView, this);
8587
MessageComposerViewModelBinding.bind(messageComposerViewModel, binding.messageComposerView, this);
8688

87-
// Step 3 - Let both MessageListHeaderView and MessageComposerView know when we open a thread
89+
// Let both ChannelHeaderView and MessageComposerView know when we open a thread
8890
messageListViewModel.getMode().observe(this, mode -> {
8991
if (mode instanceof MessageMode.MessageThread) {
9092
Message parentMessage = ((MessageMode.MessageThread) mode).getParentMessage();
91-
messageListHeaderViewModel.setActiveThread(parentMessage);
93+
channelHeaderViewModel.setActiveThread(parentMessage);
9294
messageComposerViewModel.setMessageMode(new MessageMode.MessageThread(parentMessage));
9395
} else if (mode instanceof MessageMode.Normal) {
94-
messageListHeaderViewModel.resetThread();
96+
channelHeaderViewModel.resetThread();
9597
messageComposerViewModel.leaveThread();
9698
}
9799
});
98100

99-
// Step 4 - Let the message input know when we are editing a message
101+
// Let the message input know when we are editing a message
100102
binding.messageListView.setMessageEditHandler(message -> {
101103
messageComposerViewModel.performMessageAction(new Edit(message));
102104
});
103105

104-
// Step 5 - Handle navigate up state
106+
// Handle navigate up state
105107
messageListViewModel.getState().observe(this, state -> {
106108
if (state instanceof MessageListViewModel.State.NavigateUp) {
107109
finish();
108110
}
109111
});
110112

111-
// Step 6 - Handle back button behaviour correctly when you're in a thread
112-
MessageListHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
113-
binding.messageListHeaderView.setBackButtonClickListener(backHandler);
113+
// Handle back button behaviour correctly when you're in a thread
114+
ChannelHeaderView.OnClickListener backHandler = () -> messageListViewModel.onEvent(MessageListViewModel.Event.BackButtonPressed.INSTANCE);
115+
binding.channelHeaderView.setBackButtonClickListener(backHandler);
114116
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
115117
@Override
116118
public void handleOnBackPressed() {

0 commit comments

Comments
 (0)