Merge branch 'develop' of https://github.com/GetStream/stream-chat-flutter into cds-189
This commit is contained in:
@@ -52,6 +52,8 @@ Stream's Flutter code is kept in a single mono-repository consisting of multiple
|
|||||||
|
|
||||||
`stream_chat_persistence` - This package provides a persistence client for fetching and saving chat data locally. Stream Chat Persistence uses Moor as a disk cache.
|
`stream_chat_persistence` - This package provides a persistence client for fetching and saving chat data locally. Stream Chat Persistence uses Moor as a disk cache.
|
||||||
|
|
||||||
|
`stream_chat_localizations` - This package provides a set of localizations for the SDK.
|
||||||
|
|
||||||
### Local Setup
|
### Local Setup
|
||||||
|
|
||||||
Congratulations! 🎉. You've successfully cloned our repo, and you are ready to make your first contribution. Before you can start making code changes, there are a few things to configure.
|
Congratulations! 🎉. You've successfully cloned our repo, and you are ready to make your first contribution. Before you can start making code changes, there are a few things to configure.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ This repository contains code for our [Dart](https://dart.dev/) and [Flutter](ht
|
|||||||
Stream allows developers to rapidly deploy scalable feeds and chat messaging with an industry leading 99.999% uptime SLA guarantee.
|
Stream allows developers to rapidly deploy scalable feeds and chat messaging with an industry leading 99.999% uptime SLA guarantee.
|
||||||
|
|
||||||
## Sample apps and demos
|
## Sample apps and demos
|
||||||
Our team maintains a dedicated repository for fully-fledged sample applications and demos. Consider checking out [GetStream/flutter-samples](https://github.com/GetStream/flutter-samples) to learn more or get started by looking at our latest [Stream Chat demo](https://github.com/GetStream/flutter-samples/tree/main/stream_chat_v1).
|
Our team maintains a dedicated repository for fully-fledged sample applications and demos. Consider checking out [GetStream/flutter-samples](https://github.com/GetStream/flutter-samples) to learn more or get started by looking at our latest [Stream Chat demo](https://github.com/GetStream/flutter-samples/tree/main/packages/stream_chat_v1).
|
||||||
|
|
||||||
## Free for Makers
|
## Free for Makers
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,14 @@ Exploring The Basics Of Stream Chat
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
Stream Chat is a service that helps you easily build a full chat experience in your Flutter (and more) apps.
|
Stream Chat is a service that helps you easily build a full chat experience in your Flutter apps.
|
||||||
|
We also support a variety of other SDKs.
|
||||||
|
|
||||||
This section of the documentation focuses on our Flutter SDK which helps you easily
|
This section of the documentation focuses on our Flutter SDK which helps you easily
|
||||||
ship high quality messaging experiences in apps and programs built with the [Flutter toolkit made
|
ship high quality messaging experiences in apps and programs built with the [Flutter toolkit
|
||||||
by Google](https://flutter.dev).
|
made by Google](https://flutter.dev).
|
||||||
|
|
||||||
The Stream Chat Flutter SDK comprises of four different packages to choose from ranging from ones
|
The Stream Chat Flutter SDK comprises five different packages to choose from, ranging from ones
|
||||||
giving you complete control to ones that give you a rich out-of-the-box chat experience.
|
giving you complete control to ones that give you a rich out-of-the-box chat experience.
|
||||||
|
|
||||||
The packages that make up the Stream Chat SDK are:
|
The packages that make up the Stream Chat SDK are:
|
||||||
@@ -30,28 +31,28 @@ reusable and customisable UI components.
|
|||||||
saving chat data locally.
|
saving chat data locally.
|
||||||
5. <b>Localizations (stream_chat_localizations)</b>: provides a set of localizations for the SDK.
|
5. <b>Localizations (stream_chat_localizations)</b>: provides a set of localizations for the SDK.
|
||||||
|
|
||||||
We recommend building prototypes using the full UI package since it contains UI widgets already
|
We recommend building prototypes using the full UI package, [stream_chat_flutter](https://pub.dev/packages/stream_chat_flutter),
|
||||||
integrated with Stream's API. [stream_chat_flutter](https://pub.dev/packages/stream_chat_flutter)
|
since it contains UI widgets already integrated with Stream's API. It is the fastest way to get up
|
||||||
is the fastest way to get up and running using Stream chat in your app.
|
and running using Stream chat in your app.
|
||||||
|
|
||||||
The Flutter SDK enables you to build any type of chat or messaging experience for Android, iOS, Web
|
The Flutter SDK enables you to build any type of chat or messaging experience for Android, iOS, Web
|
||||||
and Desktop.
|
and Desktop.
|
||||||
|
|
||||||
If you're building a very custom UI and would prefer a more lean package,
|
If you're building a very custom UI and would prefer a more lean package,
|
||||||
our [core package](https://pub.dev/packages/stream_chat_flutter) will be suited to this use case. Core allows you to build custom,
|
[stream_chat_flutter_core](https://pub.dev/packages/stream_chat_flutter_core) will be suited to this
|
||||||
expressive UIs while retaining the benefits of our full Flutter SDK.
|
use case. Core allows you to build custom, expressive UIs while retaining the benefits of our full
|
||||||
APIs for accessing and controlling users, sending messages, etc are seamlessly integrated into
|
Flutter SDK. APIs for accessing and controlling users, sending messages, and so forth are seamlessly integrated
|
||||||
this package and accessible via providers and builders.
|
into this package and accessible via providers and builders.
|
||||||
|
|
||||||
Before going into the docs, let's take a small detour to look at how the elements of Stream Chat are structured.
|
Before going into the docs, let's take a small detour to look at how the elements of Stream Chat are structured.
|
||||||
|
|
||||||
### Basic Structure
|
### Basic Structure
|
||||||
|
|
||||||
There are two core elements in chat, <b>Users and Channels.</b>
|
There are two core elements in chat, <b>Users</b> and <b>Channels</b>.
|
||||||
Channels are groups of one or more users that can message each other.
|
Channels are groups of one or more users that can message each other.
|
||||||
In an app, you need to have a user connected to query channels.
|
In an app, you need to have a user connected to query channels.
|
||||||
|
|
||||||
There is no specific distinction between a chat between two people and a group chat,
|
There is no specific distinction between a chat with only two people and a group chat,
|
||||||
but there is a way to create a unique chat between a certain number of people by creating a <b>distinct</b> channel.
|
but there is a way to create a unique chat between a certain number of people by creating a <b>distinct</b> channel.
|
||||||
|
|
||||||

|

|
||||||
@@ -68,7 +69,7 @@ While this is a simplistic overview of the service, the Flutter SDK handles the
|
|||||||
|
|
||||||
Before reading the docs, consider trying our [online API tour](https://getstream.io/chat/get_started/),
|
Before reading the docs, consider trying our [online API tour](https://getstream.io/chat/get_started/),
|
||||||
it is a nice way to learn how the API works.
|
it is a nice way to learn how the API works.
|
||||||
It's in-browser so Javascript-based but the ideas are pretty much the same as Dart.
|
It's in-browser so you'll need to use Javascript but the core conceps are pretty much the same as Dart.
|
||||||
|
|
||||||
You may also like to look at the [Flutter tutorial](https://getstream.io/chat/flutter/tutorial/)
|
You may also like to look at the [Flutter tutorial](https://getstream.io/chat/flutter/tutorial/)
|
||||||
which focuses on using the UI package to get Stream Chat integrated into a Flutter app.
|
which focuses on using the UI package to get Stream Chat integrated into a Flutter app.
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ At the moment we support the following languages:
|
|||||||
- [Italian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart)
|
- [Italian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart)
|
||||||
- [French](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart)
|
- [French](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart)
|
||||||
- [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart)
|
- [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart)
|
||||||
|
- [Japanese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart)
|
||||||
|
- [Korean](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart)
|
||||||
More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more languages.
|
More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more languages.
|
||||||
|
|
||||||
### Add dependency
|
### Add dependency
|
||||||
@@ -64,6 +65,8 @@ class MyApp extends StatelessWidget {
|
|||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
Locale('es'),
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
],
|
],
|
||||||
// Add GlobalStreamChatLocalizations.delegates
|
// Add GlobalStreamChatLocalizations.delegates
|
||||||
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
||||||
@@ -133,6 +136,8 @@ Here is an example of how that would look like:
|
|||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
Locale('es'),
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
],
|
],
|
||||||
// locales are the locales of the device
|
// locales are the locales of the device
|
||||||
// supportedLocales are the app supported locales
|
// supportedLocales are the app supported locales
|
||||||
@@ -175,6 +180,8 @@ Example:
|
|||||||
<string>nb</string>
|
<string>nb</string>
|
||||||
<string>fr</string>
|
<string>fr</string>
|
||||||
<string>it</string>
|
<string>it</string>
|
||||||
<string>es</string>
|
<string>es</string>
|
||||||
|
<string>ja</string>
|
||||||
|
<string>ko</string>
|
||||||
</array>
|
</array>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -153,9 +153,9 @@ class Channel {
|
|||||||
true;
|
true;
|
||||||
|
|
||||||
/// Returns true if the channel is muted, as a stream.
|
/// Returns true if the channel is muted, as a stream.
|
||||||
Stream<bool>? get isMutedStream => _client.state.currentUserStream
|
Stream<bool> get isMutedStream => _client.state.currentUserStream
|
||||||
.map((event) =>
|
.map((event) =>
|
||||||
event!.channelMutes.any((element) => element.channel.cid == cid) ==
|
event?.channelMutes.any((element) => element.channel.cid == cid) ==
|
||||||
true)
|
true)
|
||||||
.distinct();
|
.distinct();
|
||||||
|
|
||||||
@@ -168,37 +168,37 @@ class Channel {
|
|||||||
/// Channel configuration.
|
/// Channel configuration.
|
||||||
ChannelConfig? get config {
|
ChannelConfig? get config {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?._channelState.channel?.config;
|
return state!._channelState.channel?.config;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel configuration as a stream.
|
/// Channel configuration as a stream.
|
||||||
Stream<ChannelConfig?>? get configStream {
|
Stream<ChannelConfig?> get configStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.config);
|
return state!.channelStateStream.map((cs) => cs.channel?.config);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel user creator.
|
/// Channel user creator.
|
||||||
User? get createdBy {
|
User? get createdBy {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?._channelState.channel?.createdBy;
|
return state!._channelState.channel?.createdBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel user creator as a stream.
|
/// Channel user creator as a stream.
|
||||||
Stream<User?>? get createdByStream {
|
Stream<User?> get createdByStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.createdBy);
|
return state!.channelStateStream.map((cs) => cs.channel?.createdBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel frozen status.
|
/// Channel frozen status.
|
||||||
bool? get frozen {
|
bool get frozen {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?._channelState.channel?.frozen;
|
return state!._channelState.channel?.frozen == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel frozen status as a stream.
|
/// Channel frozen status as a stream.
|
||||||
Stream<bool?>? get frozenStream {
|
Stream<bool> get frozenStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.frozen);
|
return state!.channelStateStream.map((cs) => cs.channel?.frozen == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cooldown count
|
/// Cooldown count
|
||||||
@@ -219,69 +219,61 @@ class Channel {
|
|||||||
/// Channel creation date.
|
/// Channel creation date.
|
||||||
DateTime? get createdAt {
|
DateTime? get createdAt {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?._channelState.channel?.createdAt;
|
return state!._channelState.channel?.createdAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel creation date as a stream.
|
/// Channel creation date as a stream.
|
||||||
Stream<DateTime?>? get createdAtStream {
|
Stream<DateTime?> get createdAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.createdAt);
|
return state!.channelStateStream.map((cs) => cs.channel?.createdAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel last message date.
|
/// Channel last message date.
|
||||||
DateTime? get lastMessageAt {
|
DateTime? get lastMessageAt {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!._channelState.channel?.lastMessageAt;
|
||||||
return state?._channelState.channel?.lastMessageAt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel last message date as a stream.
|
/// Channel last message date as a stream.
|
||||||
Stream<DateTime?>? get lastMessageAtStream {
|
Stream<DateTime?> get lastMessageAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!.channelStateStream.map((cs) => cs.channel?.lastMessageAt);
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.lastMessageAt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel updated date.
|
/// Channel updated date.
|
||||||
DateTime? get updatedAt {
|
DateTime? get updatedAt {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!._channelState.channel?.updatedAt;
|
||||||
return state?._channelState.channel?.updatedAt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel updated date as a stream.
|
/// Channel updated date as a stream.
|
||||||
Stream<DateTime?>? get updatedAtStream {
|
Stream<DateTime?> get updatedAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!.channelStateStream.map((cs) => cs.channel?.updatedAt);
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.updatedAt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel deletion date.
|
/// Channel deletion date.
|
||||||
DateTime? get deletedAt {
|
DateTime? get deletedAt {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!._channelState.channel?.deletedAt;
|
||||||
return state?._channelState.channel?.deletedAt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel deletion date as a stream.
|
/// Channel deletion date as a stream.
|
||||||
Stream<DateTime?>? get deletedAtStream {
|
Stream<DateTime?> get deletedAtStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!.channelStateStream.map((cs) => cs.channel?.deletedAt);
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.deletedAt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel member count.
|
/// Channel member count.
|
||||||
int? get memberCount {
|
int? get memberCount {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!._channelState.channel?.memberCount;
|
||||||
return state?._channelState.channel?.memberCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel member count as a stream.
|
/// Channel member count as a stream.
|
||||||
Stream<int?>? get memberCountStream {
|
Stream<int?> get memberCountStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
|
return state!.channelStateStream.map((cs) => cs.channel?.memberCount);
|
||||||
return state?.channelStateStream.map((cs) => cs.channel?.memberCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel id.
|
/// Channel id.
|
||||||
@@ -296,7 +288,7 @@ class Channel {
|
|||||||
/// Channel team.
|
/// Channel team.
|
||||||
String? get team {
|
String? get team {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state?._channelState.channel?.team;
|
return state!._channelState.channel?.team;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Channel extra data.
|
/// Channel extra data.
|
||||||
@@ -309,7 +301,7 @@ class Channel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Channel extra data as a stream.
|
/// Channel extra data as a stream.
|
||||||
Stream<Map<String, dynamic>> get extraDataStream {
|
Stream<Map<String, Object?>> get extraDataStream {
|
||||||
_checkInitialized();
|
_checkInitialized();
|
||||||
return state!.channelStateStream.map(
|
return state!.channelStateStream.map(
|
||||||
(cs) => cs.channel?.extraData ?? _extraData,
|
(cs) => cs.channel?.extraData ?? _extraData,
|
||||||
@@ -1760,9 +1752,9 @@ class ChannelClientState {
|
|||||||
(event) {
|
(event) {
|
||||||
final readList = List<Read>.from(_channelState.read);
|
final readList = List<Read>.from(_channelState.read);
|
||||||
final userReadIndex =
|
final userReadIndex =
|
||||||
read?.indexWhere((r) => r.user.id == event.user!.id);
|
read.indexWhere((r) => r.user.id == event.user!.id);
|
||||||
|
|
||||||
if (userReadIndex != null && userReadIndex != -1) {
|
if (userReadIndex != -1) {
|
||||||
final userRead = readList.removeAt(userReadIndex);
|
final userRead = readList.removeAt(userReadIndex);
|
||||||
if (userRead.user.id == _channel._client.state.currentUser!.id) {
|
if (userRead.user.id == _channel._client.state.currentUser!.id) {
|
||||||
unreadCount = 0;
|
unreadCount = 0;
|
||||||
@@ -1783,15 +1775,15 @@ class ChannelClientState {
|
|||||||
List<Message> get messages => _channelState.messages;
|
List<Message> get messages => _channelState.messages;
|
||||||
|
|
||||||
/// Channel message list as a stream.
|
/// Channel message list as a stream.
|
||||||
Stream<List<Message>?> get messagesStream => channelStateStream
|
Stream<List<Message>> get messagesStream => channelStateStream
|
||||||
.map((cs) => cs.messages)
|
.map((cs) => cs.messages)
|
||||||
.distinct(const ListEquality().equals);
|
.distinct(const ListEquality().equals);
|
||||||
|
|
||||||
/// Channel pinned message list.
|
/// Channel pinned message list.
|
||||||
List<Message>? get pinnedMessages => _channelState.pinnedMessages.toList();
|
List<Message> get pinnedMessages => _channelState.pinnedMessages.toList();
|
||||||
|
|
||||||
/// Channel pinned message list as a stream.
|
/// Channel pinned message list as a stream.
|
||||||
Stream<List<Message>?> get pinnedMessagesStream =>
|
Stream<List<Message>> get pinnedMessagesStream =>
|
||||||
channelStateStream.map((cs) => cs.pinnedMessages.toList());
|
channelStateStream.map((cs) => cs.pinnedMessages.toList());
|
||||||
|
|
||||||
/// Get channel last message.
|
/// Get channel last message.
|
||||||
@@ -1800,8 +1792,8 @@ class ChannelClientState {
|
|||||||
: null;
|
: null;
|
||||||
|
|
||||||
/// Get channel last message.
|
/// Get channel last message.
|
||||||
Stream<Message?> get lastMessageStream => messagesStream
|
Stream<Message?> get lastMessageStream =>
|
||||||
.map((event) => event?.isNotEmpty == true ? event!.last : null);
|
messagesStream.map((event) => event.isNotEmpty ? event.last : null);
|
||||||
|
|
||||||
/// Channel members list.
|
/// Channel members list.
|
||||||
List<Member> get members => _channelState.members
|
List<Member> get members => _channelState.members
|
||||||
@@ -1838,10 +1830,10 @@ class ChannelClientState {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/// Channel read list.
|
/// Channel read list.
|
||||||
List<Read>? get read => _channelState.read;
|
List<Read> get read => _channelState.read;
|
||||||
|
|
||||||
/// Channel read list as a stream.
|
/// Channel read list as a stream.
|
||||||
Stream<List<Read>?> get readStream => channelStateStream.map((cs) => cs.read);
|
Stream<List<Read>> get readStream => channelStateStream.map((cs) => cs.read);
|
||||||
|
|
||||||
final BehaviorSubject<int> _unreadCountController = BehaviorSubject.seeded(0);
|
final BehaviorSubject<int> _unreadCountController = BehaviorSubject.seeded(0);
|
||||||
|
|
||||||
@@ -2092,7 +2084,7 @@ class ChannelClientState {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
updateChannelState(_channelState.copyWith(
|
updateChannelState(_channelState.copyWith(
|
||||||
pinnedMessages: pinnedMessages!.where(_pinIsValid()).toList(),
|
pinnedMessages: pinnedMessages.where(_pinIsValid()).toList(),
|
||||||
messages: expiredMessages,
|
messages: expiredMessages,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ breakdown:
|
|||||||
🐞 Fixed
|
🐞 Fixed
|
||||||
|
|
||||||
- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the camera is null.
|
- Fixed `MessageInput` textField case where `input` is not enabled if the file picked from the camera is null.
|
||||||
|
- Fixed date dividers position/alignment in non reversed `MessageListView`.
|
||||||
|
|
||||||
## 2.1.2
|
## 2.1.2
|
||||||
|
|
||||||
|
|||||||
@@ -584,11 +584,16 @@ class _ChannelListViewState extends State<ChannelListView> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
child: widget.channelPreviewBuilder?.call(context, channel) ??
|
child: widget.channelPreviewBuilder?.call(context, channel) ??
|
||||||
ChannelPreview(
|
DecoratedBox(
|
||||||
onLongPress: widget.onChannelLongPress,
|
decoration: BoxDecoration(
|
||||||
channel: channel,
|
color: chatThemeData.channelListViewTheme.backgroundColor,
|
||||||
onImageTap: () => widget.onImageTap?.call(channel),
|
),
|
||||||
onTap: (channel) => onTap(channel, widget.channelWidget),
|
child: ChannelPreview(
|
||||||
|
onLongPress: widget.onChannelLongPress,
|
||||||
|
channel: channel,
|
||||||
|
onImageTap: () => widget.onImageTap?.call(channel),
|
||||||
|
onTap: (channel) => onTap(channel, widget.channelWidget),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class ChannelPreview extends StatelessWidget {
|
|||||||
message: lastMessage!,
|
message: lastMessage!,
|
||||||
size: channelPreviewTheme.indicatorIconSize,
|
size: channelPreviewTheme.indicatorIconSize,
|
||||||
isMessageRead: channel.state!.read
|
isMessageRead: channel.state!.read
|
||||||
?.where((element) =>
|
.where((element) =>
|
||||||
element.user.id !=
|
element.user.id !=
|
||||||
channel
|
channel
|
||||||
.client.state.currentUser!.id)
|
.client.state.currentUser!.id)
|
||||||
|
|||||||
@@ -142,9 +142,9 @@ class _GalleryFooterState extends State<GalleryFooter> {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
'${widget.currentPage + 1} '
|
context.translations.galleryPaginationText(
|
||||||
'${context.translations.ofText} '
|
currentPage: widget.currentPage,
|
||||||
'${widget.totalPages}',
|
totalPages: widget.totalPages),
|
||||||
style: galleryFooterThemeData.titleTextStyle,
|
style: galleryFooterThemeData.titleTextStyle,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -299,8 +299,9 @@ abstract class Translations {
|
|||||||
/// The text shown for "You"
|
/// The text shown for "You"
|
||||||
String get youText;
|
String get youText;
|
||||||
|
|
||||||
/// The text shown for "Of"
|
/// Gallery footer pagination text
|
||||||
String get ofText;
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages});
|
||||||
|
|
||||||
/// The text shown for "File"
|
/// The text shown for "File"
|
||||||
String get fileText;
|
String get fileText;
|
||||||
@@ -660,7 +661,9 @@ class DefaultTranslations implements Translations {
|
|||||||
String get youText => 'You';
|
String get youText => 'You';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'of';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} of $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'File';
|
String get fileText => 'File';
|
||||||
|
|||||||
@@ -505,8 +505,14 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
|
|
||||||
if (i == 1 || i == itemCount - 4) return const Offstage();
|
if (i == 1 || i == itemCount - 4) return const Offstage();
|
||||||
|
|
||||||
final message = messages[i - 1];
|
late final Message message, nextMessage;
|
||||||
final nextMessage = messages[i - 2];
|
if (widget.reverse) {
|
||||||
|
message = messages[i - 1];
|
||||||
|
nextMessage = messages[i - 2];
|
||||||
|
} else {
|
||||||
|
message = messages[i - 2];
|
||||||
|
nextMessage = messages[i - 1];
|
||||||
|
}
|
||||||
if (!Jiffy(message.createdAt.toLocal()).isSame(
|
if (!Jiffy(message.createdAt.toLocal()).isSame(
|
||||||
nextMessage.createdAt.toLocal(),
|
nextMessage.createdAt.toLocal(),
|
||||||
Units.DAY,
|
Units.DAY,
|
||||||
@@ -636,8 +642,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Positioned _buildFloatingDateDivider(int itemCount) => Positioned(
|
Positioned _buildFloatingDateDivider(int itemCount) => Positioned(
|
||||||
top: widget.reverse ? 20 : null,
|
top: 20,
|
||||||
bottom: widget.reverse ? null : 20,
|
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
child: BetterStreamBuilder<Iterable<ItemPosition>>(
|
child: BetterStreamBuilder<Iterable<ItemPosition>>(
|
||||||
@@ -647,19 +652,36 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
if (a == null || b == null) {
|
if (a == null || b == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final aTop = _getTopElementIndex(a);
|
if (widget.reverse) {
|
||||||
final bTop = _getTopElementIndex(b);
|
final aTop = _getTopElementIndex(a);
|
||||||
return aTop == bTop;
|
final bTop = _getTopElementIndex(b);
|
||||||
|
return aTop == bTop;
|
||||||
|
} else {
|
||||||
|
final aBottom = _getBottomElementIndex(a);
|
||||||
|
final bBottom = _getBottomElementIndex(b);
|
||||||
|
return aBottom == bBottom;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
builder: (context, values) {
|
builder: (context, values) {
|
||||||
if (values.isEmpty || messages.isEmpty) {
|
if (values.isEmpty || messages.isEmpty) {
|
||||||
return const Offstage();
|
return const Offstage();
|
||||||
}
|
}
|
||||||
|
|
||||||
final index = _getTopElementIndex(values);
|
int? index;
|
||||||
|
if (widget.reverse) {
|
||||||
|
index = _getTopElementIndex(values);
|
||||||
|
} else {
|
||||||
|
index = _getBottomElementIndex(values);
|
||||||
|
}
|
||||||
|
|
||||||
if (index == null || index <= 2 || index >= itemCount - 3) {
|
if (index == null) return const Offstage();
|
||||||
return const Offstage();
|
|
||||||
|
if (index <= 2 || index >= itemCount - 3) {
|
||||||
|
if (widget.reverse) {
|
||||||
|
index = itemCount - 4;
|
||||||
|
} else {
|
||||||
|
index = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final message = messages[index - 2];
|
final message = messages[index - 2];
|
||||||
@@ -685,6 +707,15 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
.index;
|
.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int? _getBottomElementIndex(Iterable<ItemPosition> values) {
|
||||||
|
final inView = values.where((position) => position.itemLeadingEdge < 1);
|
||||||
|
if (inView.isEmpty) return null;
|
||||||
|
return inView
|
||||||
|
.reduce((min, position) =>
|
||||||
|
position.itemLeadingEdge < min.itemLeadingEdge ? position : min)
|
||||||
|
.index;
|
||||||
|
}
|
||||||
|
|
||||||
Widget _buildScrollToBottom() => StreamBuilder<Tuple2<bool, int>>(
|
Widget _buildScrollToBottom() => StreamBuilder<Tuple2<bool, int>>(
|
||||||
stream: Rx.combineLatest2(
|
stream: Rx.combineLatest2(
|
||||||
streamChannel!.channel.state!.isUpToDateStream.distinct(),
|
streamChannel!.channel.state!.isUpToDateStream.distinct(),
|
||||||
@@ -915,7 +946,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final channel = streamChannel!.channel;
|
final channel = streamChannel!.channel;
|
||||||
final readList = channel.state?.read?.where((read) {
|
final readList = channel.state?.read.where((read) {
|
||||||
if (read.user.id == userId) return false;
|
if (read.user.id == userId) return false;
|
||||||
return read.lastRead.isAfter(message.createdAt) ||
|
return read.lastRead.isAfter(message.createdAt) ||
|
||||||
read.lastRead.isAtSameMomentAs(message.createdAt);
|
read.lastRead.isAtSameMomentAs(message.createdAt);
|
||||||
@@ -1203,8 +1234,7 @@ class _MessageListViewState extends State<MessageListView> {
|
|||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (_) => BetterStreamBuilder<Message>(
|
builder: (_) => BetterStreamBuilder<Message>(
|
||||||
stream: streamChannel!.channel.state!.messagesStream.map(
|
stream: streamChannel!.channel.state!.messagesStream.map(
|
||||||
(messages) =>
|
(messages) => messages.firstWhere((m) => m.id == message.id)),
|
||||||
messages!.firstWhere((m) => m.id == message.id)),
|
|
||||||
initialData: message,
|
initialData: message,
|
||||||
builder: (_, data) => StreamChannel(
|
builder: (_, data) => StreamChannel(
|
||||||
channel: streamChannel!.channel,
|
channel: streamChannel!.channel,
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ void main() {
|
|||||||
when(() => clientState.currentUser).thenReturn(user);
|
when(() => clientState.currentUser).thenReturn(user);
|
||||||
when(() => clientState.currentUserStream)
|
when(() => clientState.currentUserStream)
|
||||||
.thenAnswer((_) => Stream.value(user));
|
.thenAnswer((_) => Stream.value(user));
|
||||||
|
when(() => channel.lastMessageAtStream)
|
||||||
|
.thenAnswer((_) => Stream.value(lastMessageAt));
|
||||||
when(() => channel.lastMessageAt).thenReturn(lastMessageAt);
|
when(() => channel.lastMessageAt).thenReturn(lastMessageAt);
|
||||||
when(() => channel.state).thenReturn(channelState);
|
when(() => channel.state).thenReturn(channelState);
|
||||||
when(() => channel.client).thenReturn(client);
|
when(() => channel.client).thenReturn(client);
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ void main() {
|
|||||||
expect(translations.withText, isNotNull);
|
expect(translations.withText, isNotNull);
|
||||||
expect(translations.inText, isNotNull);
|
expect(translations.inText, isNotNull);
|
||||||
expect(translations.youText, isNotNull);
|
expect(translations.youText, isNotNull);
|
||||||
expect(translations.ofText, isNotNull);
|
expect(translations.galleryPaginationText, isNotNull);
|
||||||
expect(translations.fileText, isNotNull);
|
expect(translations.fileText, isNotNull);
|
||||||
expect(translations.replyToMessageLabel, isNotNull);
|
expect(translations.replyToMessageLabel, isNotNull);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## Upcoming
|
||||||
|
|
||||||
|
🐞 Fixed
|
||||||
|
- [#612](https://github.com/GetStream/stream-chat-flutter/issues/612) `ChannelListView` pagination doesn't work after refresh
|
||||||
|
|
||||||
## 2.1.1
|
## 2.1.1
|
||||||
|
|
||||||
- Updated llc dependency
|
- Updated llc dependency
|
||||||
|
|||||||
@@ -106,6 +106,9 @@ class ChannelsBlocState extends State<ChannelsBloc>
|
|||||||
final client = _streamChatCoreState!.client;
|
final client = _streamChatCoreState!.client;
|
||||||
|
|
||||||
final clear = paginationParams.offset == 0;
|
final clear = paginationParams.offset == 0;
|
||||||
|
if (clear && _paginationEnded) {
|
||||||
|
_paginationEnded = false;
|
||||||
|
}
|
||||||
|
|
||||||
if ((!clear && _paginationEnded) ||
|
if ((!clear && _paginationEnded) ||
|
||||||
_queryChannelsLoadingController.value == true) {
|
_queryChannelsLoadingController.value == true) {
|
||||||
|
|||||||
@@ -1,7 +1,19 @@
|
|||||||
## Upcoming
|
## Upcoming
|
||||||
|
|
||||||
* Added support for [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart) locale.
|
✅ Added
|
||||||
|
|
||||||
|
* Added support for [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart) locale.
|
||||||
|
* Added support for [Korean](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart) locale.
|
||||||
|
* Added support for [Japanese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart) locale.
|
||||||
|
|
||||||
|
🔄 Changed
|
||||||
|
|
||||||
|
* Some of the `Hindi` translations have been updated/changed for better understanding.
|
||||||
|
- 'रिप्लाई' -> 'जवाब दें'
|
||||||
|
- 'तस्वीरें' -> 'फ़ोटोज'
|
||||||
|
- 'बिता हुआ कल' -> 'कल'
|
||||||
|
- 'चैनल मौन है' -> 'चैनल म्यूट है'
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
|
|
||||||
* Updated `stream_chat_flutter` dependency
|
* Updated `stream_chat_flutter` dependency
|
||||||
|
|||||||
@@ -35,6 +35,8 @@ At the moment we support the following languages:
|
|||||||
- [Italian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart)
|
- [Italian](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_it.dart)
|
||||||
- [French](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart)
|
- [French](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_fr.dart)
|
||||||
- [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart)
|
- [Spanish](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_es.dart)
|
||||||
|
- [Japanese](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ja.dart)
|
||||||
|
- [Korean](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat_localizations/lib/src/stream_chat_localizations_ko.dart)
|
||||||
|
|
||||||
More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more languages.
|
More languages will be added in the future. Feel free to [contribute](https://github.com/GetStream/stream-chat-flutter/blob/master/CONTRIBUTING.md) to add more languages.
|
||||||
|
|
||||||
@@ -70,6 +72,8 @@ class MyApp extends StatelessWidget {
|
|||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
Locale('es'),
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
],
|
],
|
||||||
// Add GlobalStreamChatLocalizations.delegates
|
// Add GlobalStreamChatLocalizations.delegates
|
||||||
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
||||||
@@ -113,6 +117,8 @@ Example:
|
|||||||
<string>fr</string>
|
<string>fr</string>
|
||||||
<string>it</string>
|
<string>it</string>
|
||||||
<string>es</string>
|
<string>es</string>
|
||||||
|
<string>ja</string>
|
||||||
|
<string>ko</string>
|
||||||
</array>
|
</array>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -374,7 +374,9 @@ class NnStreamChatLocalizations extends GlobalStreamChatLocalizations {
|
|||||||
String get youText => 'You';
|
String get youText => 'You';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'of';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'$currentPage of $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'File';
|
String get fileText => 'File';
|
||||||
@@ -456,6 +458,9 @@ class MyApp extends StatelessWidget {
|
|||||||
Locale('hi'),
|
Locale('hi'),
|
||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
// Add support for additional 'nn' locale
|
// Add support for additional 'nn' locale
|
||||||
Locale('nn'),
|
Locale('nn'),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ class MyApp extends StatelessWidget {
|
|||||||
Locale('hi'),
|
Locale('hi'),
|
||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
],
|
],
|
||||||
// Add GlobalStreamChatLocalizations.delegates
|
// Add GlobalStreamChatLocalizations.delegates
|
||||||
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ class MyApp extends StatelessWidget {
|
|||||||
Locale('hi'),
|
Locale('hi'),
|
||||||
Locale('fr'),
|
Locale('fr'),
|
||||||
Locale('it'),
|
Locale('it'),
|
||||||
|
Locale('es'),
|
||||||
|
Locale('ja'),
|
||||||
|
Locale('ko'),
|
||||||
],
|
],
|
||||||
// Add overridden "CustomStreamChatLocalizationsEn.delegate" along with
|
// Add overridden "CustomStreamChatLocalizationsEn.delegate" along with
|
||||||
// "GlobalStreamChatLocalizations.delegates"
|
// "GlobalStreamChatLocalizations.delegates"
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ part 'stream_chat_localizations_fr.dart';
|
|||||||
|
|
||||||
part 'stream_chat_localizations_it.dart';
|
part 'stream_chat_localizations_it.dart';
|
||||||
|
|
||||||
|
part 'stream_chat_localizations_ja.dart';
|
||||||
|
|
||||||
|
part 'stream_chat_localizations_ko.dart';
|
||||||
|
|
||||||
part 'stream_chat_localizations_hi.dart';
|
part 'stream_chat_localizations_hi.dart';
|
||||||
|
|
||||||
/// The set of supported languages, as language code strings.
|
/// The set of supported languages, as language code strings.
|
||||||
@@ -27,6 +31,8 @@ const kStreamChatSupportedLanguages = {
|
|||||||
'fr',
|
'fr',
|
||||||
'it',
|
'it',
|
||||||
'es',
|
'es',
|
||||||
|
'ja',
|
||||||
|
'ko'
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`.
|
/// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`.
|
||||||
@@ -59,6 +65,10 @@ GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) {
|
|||||||
return const StreamChatLocalizationsIt();
|
return const StreamChatLocalizationsIt();
|
||||||
case 'es':
|
case 'es':
|
||||||
return const StreamChatLocalizationsEs();
|
return const StreamChatLocalizationsEs();
|
||||||
|
case 'ja':
|
||||||
|
return const StreamChatLocalizationsJa();
|
||||||
|
case 'ko':
|
||||||
|
return const StreamChatLocalizationsKo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -350,7 +350,9 @@ class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations {
|
|||||||
String get youText => 'You';
|
String get youText => 'You';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'of';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} of $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'File';
|
String get fileText => 'File';
|
||||||
|
|||||||
@@ -355,7 +355,9 @@ class StreamChatLocalizationsEs extends GlobalStreamChatLocalizations {
|
|||||||
String get youText => 'Usted';
|
String get youText => 'Usted';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'de';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} de $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'Archivo';
|
String get fileText => 'Archivo';
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ class StreamChatLocalizationsFr extends GlobalStreamChatLocalizations {
|
|||||||
@override
|
@override
|
||||||
String togglePinUnpinText({required bool pinned}) {
|
String togglePinUnpinText({required bool pinned}) {
|
||||||
if (pinned) return 'Décrocher de la conversation';
|
if (pinned) return 'Décrocher de la conversation';
|
||||||
return 'Épingler à la discussion';
|
return 'Épingler à la conversation';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -354,7 +354,9 @@ class StreamChatLocalizationsFr extends GlobalStreamChatLocalizations {
|
|||||||
String get youText => 'Vous';
|
String get youText => 'Vous';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'de';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} de $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'Fichier';
|
String get fileText => 'Fichier';
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
|
|||||||
'कार्रवाई पूरी नहीं की जा सकी.';
|
'कार्रवाई पूरी नहीं की जा सकी.';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get replyLabel => 'रिप्लाई';
|
String get replyLabel => 'जवाब दें';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String togglePinUnpinText({required bool pinned}) {
|
String togglePinUnpinText({required bool pinned}) {
|
||||||
@@ -224,7 +224,7 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get photosLabel => 'तस्वीरें';
|
String get photosLabel => 'फ़ोटोज';
|
||||||
|
|
||||||
String _getDay(DateTime dateTime) {
|
String _getDay(DateTime dateTime) {
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
@@ -250,10 +250,10 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
|
|||||||
String get todayLabel => 'आज';
|
String get todayLabel => 'आज';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get yesterdayLabel => 'बिता हुआ कल';
|
String get yesterdayLabel => 'कल';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get channelIsMutedText => 'चैनल मौन है';
|
String get channelIsMutedText => 'चैनल म्यूट है';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get noTitleText => 'कोई शीर्षक नहीं';
|
String get noTitleText => 'कोई शीर्षक नहीं';
|
||||||
@@ -340,16 +340,18 @@ class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
|
|||||||
String get sendLabel => 'भेजें';
|
String get sendLabel => 'भेजें';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get withText => 'विद';
|
String get withText => 'विद'; //TODO: break?
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get inText => 'इन';
|
String get inText => 'इन'; //TODO: break?
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get youText => 'आप';
|
String get youText => 'आप';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'ऑफ़';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} ऑफ़ $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'फ़ाइल';
|
String get fileText => 'फ़ाइल';
|
||||||
|
|||||||
@@ -351,7 +351,9 @@ Il file è troppo grande per essere caricato. Il limite è di $limitInMB MB.''';
|
|||||||
String get youText => 'te';
|
String get youText => 'te';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get ofText => 'di';
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} di $totalPages';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get fileText => 'file';
|
String get fileText => 'file';
|
||||||
|
|||||||
@@ -0,0 +1,349 @@
|
|||||||
|
part of 'stream_chat_localizations.dart';
|
||||||
|
|
||||||
|
/// The translations for Japanese (`ja`).
|
||||||
|
class StreamChatLocalizationsJa extends GlobalStreamChatLocalizations {
|
||||||
|
/// Create an instance of the translation bundle for Japanese.
|
||||||
|
const StreamChatLocalizationsJa({String localeName = 'ja'})
|
||||||
|
: super(localeName: localeName);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get launchUrlError => 'URLの起動ができません';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingUsersError => 'ユーザーの読み込みができません';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noUsersLabel => '現在、ユーザーはいません。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get retryLabel => '再試行';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get userLastOnlineText => '前回のオンライン';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get userOnlineText => 'オンライン';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String userTypingText(Iterable<User> users) {
|
||||||
|
if (users.isEmpty) return '';
|
||||||
|
final first = users.first;
|
||||||
|
if (users.length == 1) {
|
||||||
|
return '${first.name}が入力しています';
|
||||||
|
}
|
||||||
|
return '${first.name}と${users.length - 1}人が入力しています';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get threadReplyLabel => 'スレッド返信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get onlyVisibleToYouText => '自分しか見れません';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String threadReplyCountText(int count) => '$countつのスレッド返信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String attachmentsUploadProgressText({
|
||||||
|
required int remaining,
|
||||||
|
required int total,
|
||||||
|
}) =>
|
||||||
|
'$remaining/${total}mbのアップロード中 。。。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String pinnedByUserText({
|
||||||
|
required User pinnedBy,
|
||||||
|
required User currentUser,
|
||||||
|
}) {
|
||||||
|
final pinnedByCurrentUser = currentUser.id == pinnedBy.id;
|
||||||
|
if (pinnedByCurrentUser) return 'あなたのピン';
|
||||||
|
return '${pinnedBy.name}のピン';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get emptyMessagesText => '現在、メッセージはありません。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get genericErrorText => 'エラーが発生しました';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingMessagesError => 'メッセージの読み込みエラー';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String resultCountText(int count) => '$count件の結果';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageDeletedText => 'このメッセージは削除されました。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageDeletedLabel => 'メッセージ削除';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageReactionsLabel => 'メッセージのリアクション';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get emptyChatMessagesText => 'チャットがありませんが。。。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String threadSeparatorText(int replyCount) => '$replyCount件の返信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get connectedLabel => '接続しています';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get disconnectedLabel => '接続切れ';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get reconnectingLabel => '再接続中。。。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get alsoSendAsDirectMessageLabel => 'ダイレクトメッセージでも送信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addACommentOrSendLabel => 'コメントの追加や送信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get searchGifLabel => 'GIFの検索';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get writeAMessageLabel => 'メッセージを書く';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get instantCommandsLabel => 'インスタントコマンド';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String fileTooLargeAfterCompressionError(double limitInMB) =>
|
||||||
|
'ファイルのサイズが大きすぎてアップロードできません。'
|
||||||
|
'ファイルサイズの制限は${limitInMB}MBです。'
|
||||||
|
'圧縮してみましたが、十分ではありませんでした。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String fileTooLargeError(double limitInMB) =>
|
||||||
|
'ファイルが大きすぎてアップロードできません。ファイルサイズの制限は${limitInMB}MBです。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String emojiMatchingQueryText(String query) => '「"$query"」とお揃いの絵文字';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addAFileLabel => 'ファイルの追加';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get photoFromCameraLabel => 'カメラからの写真';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAFileLabel => 'ファイルのアップロード';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAPhotoLabel => '写真のアップロード';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAVideoLabel => '動画のアップロード';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get videoFromCameraLabel => 'カメラからの動画';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get okLabel => 'よし';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get somethingWentWrongError => 'エラーが発生しました';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addMoreFilesLabel => 'ファイルの追加';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enablePhotoAndVideoAccessMessage => 'お友達と共有できるように、写真'
|
||||||
|
'\nやビデオへのアクセスを有効にしてください。';
|
||||||
|
@override
|
||||||
|
String get allowGalleryAccessMessage => 'ギャラリーへのアクセスを許可する';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageLabel => 'メッセージをフラグする';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageQuestion => 'このメッセージのコピーを'
|
||||||
|
'\nモデレーターに送って、さらに調査してもらいますか?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagLabel => 'フラグする';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get cancelLabel => 'キャンセル';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageSuccessfulLabel => 'メッセージにフラグが付けられました';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageSuccessfulText => 'このメッセージはモデレーターに報告されました。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteLabel => '削除';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteMessageLabel => 'メッセージを削除する ';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteMessageQuestion => 'このメッセージ'
|
||||||
|
'\nを完全に削除してもよろしいですか?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get operationCouldNotBeCompletedText => '操作を完了できませんでした。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get replyLabel => '返信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String togglePinUnpinText({required bool pinned}) {
|
||||||
|
if (pinned) return '会話のピンを外す';
|
||||||
|
return '会話にピンする';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toggleDeleteRetryDeleteMessageText({required bool isDeleteFailed}) {
|
||||||
|
if (isDeleteFailed) return 'メッセージの削除を再試行する';
|
||||||
|
return 'メッセージを削除する';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get copyMessageLabel => 'メッセージをコピーする';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get editMessageLabel => 'メッセージを編集する';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toggleResendOrResendEditedMessage({required bool isUpdateFailed}) {
|
||||||
|
if (isUpdateFailed) return '編集したメッセージを再送する';
|
||||||
|
return '再送';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get photosLabel => '写真';
|
||||||
|
|
||||||
|
String _getDay(DateTime dateTime) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final today = DateTime(now.year, now.month, now.day);
|
||||||
|
final yesterday = DateTime(now.year, now.month, now.day - 1);
|
||||||
|
|
||||||
|
final date = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||||
|
|
||||||
|
if (date == today) {
|
||||||
|
return '今日';
|
||||||
|
} else if (date == yesterday) {
|
||||||
|
return '昨日';
|
||||||
|
} else {
|
||||||
|
return '${Jiffy(date).MMMd}に';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String sentAtText({required DateTime date, required DateTime time}) =>
|
||||||
|
'${_getDay(date)}の${Jiffy(time.toLocal()).format('HH:mm')}に送信しました ';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get todayLabel => '今日';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get yesterdayLabel => '昨日';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get channelIsMutedText => 'チャンネルが無音されています';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noTitleText => 'タイトル無し';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get letsStartChattingLabel => 'チャットを始めよう!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendingFirstMessageLabel => '友人に最初のメッセージを送りましょうか?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startAChatLabel => 'チャットを開始する';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingChannelsError => 'チャネルのロード中にエラーが発生しました';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteConversationLabel => '会話を削除する';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteConversationQuestion => '本当に会話を削除しますか?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get streamChatLabel => 'ストリームチャット';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get searchingForNetworkText => 'ネットワークを検索中';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get offlineLabel => 'オフライン。。。';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tryAgainLabel => '再試行する';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String membersCountText(int count) => '$count人のメンバー';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String watchersCountText(int count) => '$count人がオンライン';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get viewInfoLabel => '情報を見る';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveGroupLabel => 'グループを離れる';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveLabel => '離れる';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveConversationLabel => '会話を離れる';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveConversationQuestion => '本当に会話を離れますか?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showInChatLabel => 'チャットで表示';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get saveImageLabel => '画像を保存';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get saveVideoLabel => 'ビデオを保存';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadErrorLabel => 'アップロードエラー';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get giphyLabel => 'ギフィー';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get shuffleLabel => 'ミックス';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendLabel => '送信';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get withText => 'と';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get inText => 'に';
|
||||||
|
|
||||||
|
// This is the word for 'customer' or 'user' because saying 'you' directly
|
||||||
|
//is too informal and rude
|
||||||
|
@override
|
||||||
|
String get youText => 'あなた';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String galleryPaginationText({
|
||||||
|
required int currentPage,
|
||||||
|
required int totalPages,
|
||||||
|
}) =>
|
||||||
|
'${currentPage + 1} / $totalPages';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fileText => 'ファイル';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get replyToMessageLabel => 'メッセージに返信';
|
||||||
|
}
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
part of 'stream_chat_localizations.dart';
|
||||||
|
|
||||||
|
/// The translations for Korean (`ko`).
|
||||||
|
class StreamChatLocalizationsKo extends GlobalStreamChatLocalizations {
|
||||||
|
/// Create an instance of the translation bundle for Korean.
|
||||||
|
const StreamChatLocalizationsKo({String localeName = 'ko'})
|
||||||
|
: super(localeName: localeName);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get launchUrlError => 'URL을 시작할 수 없습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingUsersError => '사용자를 로드하는 중 오류 발생';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noUsersLabel => '현재 사용자가 없습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get retryLabel => '다시 시도하십시오';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get userLastOnlineText => '마지막 온라인입니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get userOnlineText => '온라인';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String userTypingText(Iterable<User> users) {
|
||||||
|
if (users.isEmpty) return '';
|
||||||
|
final first = users.first;
|
||||||
|
if (users.length == 1) {
|
||||||
|
return '${first.name} 타이핑중';
|
||||||
|
}
|
||||||
|
return '${first.name}하고 ${users.length - 1}명 타이핑중';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get threadReplyLabel => '스레드 응답입니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get onlyVisibleToYouText => '당신만 볼 수 있습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String threadReplyCountText(int count) => '$count스레드 답장';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String attachmentsUploadProgressText({
|
||||||
|
required int remaining,
|
||||||
|
required int total,
|
||||||
|
}) =>
|
||||||
|
'$remaining/${total}mb를 업로드중...';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String pinnedByUserText({
|
||||||
|
required User pinnedBy,
|
||||||
|
required User currentUser,
|
||||||
|
}) {
|
||||||
|
final pinnedByCurrentUser = currentUser.id == pinnedBy.id;
|
||||||
|
if (pinnedByCurrentUser) return '당신의 핀';
|
||||||
|
return '${pinnedBy.name}의 핀';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get emptyMessagesText => '현재 메시지가 없습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get genericErrorText => '뭔가 잘못됐습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingMessagesError => '메시지를 로드하는 동안 오류가 발생했습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String resultCountText(int count) => '$count개의 결과';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageDeletedText => '이 메시지는 삭제되었습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageDeletedLabel => '메시지가 삭제되었습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get messageReactionsLabel => '메시지에 대한 응답';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get emptyChatMessagesText => '아직 채팅이 없습니다...';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String threadSeparatorText(int replyCount) => '$replyCount개의 답장';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get connectedLabel => '연결중';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get disconnectedLabel => '연결이 끊겼습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get reconnectingLabel => '다시 연결하는 중...';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get alsoSendAsDirectMessageLabel => '다이렉트 메시지로도 보냅니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addACommentOrSendLabel => '주석을 추가하거나 보냅니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get searchGifLabel => 'GIF 검색';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get writeAMessageLabel => '메시지 쓰기';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get instantCommandsLabel => '인스턴트 커맨즈';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String fileTooLargeAfterCompressionError(double limitInMB) =>
|
||||||
|
'파일이 너무 커서 업로드할 수 없습니다. '
|
||||||
|
'파일 크기 제한은 ${limitInMB}MB입니다. '
|
||||||
|
'우리는 압축해 보았지만 충분하지 않았습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String fileTooLargeError(double limitInMB) =>
|
||||||
|
'파일이 너무 커서 업로드할 수 없습니다. 파일 크기 제한은 ${limitInMB}MB입니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String emojiMatchingQueryText(String query) => '"$query"과 일치하는 이모티콘입니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addAFileLabel => '파일을 추가함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get photoFromCameraLabel => '카메라에서 찍은 사진';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAFileLabel => '파일을 업로드함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAPhotoLabel => '사진을 업로드함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadAVideoLabel => '비디오를 업로드함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get videoFromCameraLabel => '카메라의 비디오.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get okLabel => '확인';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get somethingWentWrongError => '뭔가 잘못됐습느다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get addMoreFilesLabel => '파일을 추가함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get enablePhotoAndVideoAccessMessage => '친구와 공유할 수 있도록 사진과'
|
||||||
|
'\n동영상에 액세스할 수 있도록 설정하십시오.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get allowGalleryAccessMessage => '갤러리에 대한 액세스를 허용합니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageLabel => ' 메시지를 플래그함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageQuestion => '추가 조사를 위해 진행자에게 이 메시지의 복사본을 전송하시겠습니까?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagLabel => '플래그함';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get cancelLabel => '취소';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageSuccessfulLabel => '메시지에 플래그가 지정되었습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get flagMessageSuccessfulText => '메시지가 진행자에게 보고되었습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteLabel => '삭제';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteMessageLabel => '메시지를 삭제합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteMessageQuestion => '이 메시지를 완전히 삭제하시겠습니까?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get operationCouldNotBeCompletedText => '작업을 완료할 수 없습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get replyLabel => '답글';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String togglePinUnpinText({required bool pinned}) {
|
||||||
|
if (pinned) return '대화의 핀을 분리합니다';
|
||||||
|
return '대화에 고정합니다';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toggleDeleteRetryDeleteMessageText({required bool isDeleteFailed}) {
|
||||||
|
if (isDeleteFailed) return '메시지 삭제를 다시 시도합니다';
|
||||||
|
return '메시지를 삭제합니다';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get copyMessageLabel => '메시지를 복사합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get editMessageLabel => '메시지를 편집합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toggleResendOrResendEditedMessage({required bool isUpdateFailed}) {
|
||||||
|
if (isUpdateFailed) return '편집된 메시지를 다시 보냅니다.';
|
||||||
|
return '다시 보냅니다.';
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get photosLabel => '사진';
|
||||||
|
|
||||||
|
String _getDay(DateTime dateTime) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final today = DateTime(now.year, now.month, now.day);
|
||||||
|
final yesterday = DateTime(now.year, now.month, now.day - 1);
|
||||||
|
|
||||||
|
final date = DateTime(dateTime.year, dateTime.month, dateTime.day);
|
||||||
|
|
||||||
|
if (date == today) {
|
||||||
|
return '오늘';
|
||||||
|
} else if (date == yesterday) {
|
||||||
|
return '어제';
|
||||||
|
} else {
|
||||||
|
return '${Jiffy(date).MMMd}에';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String sentAtText({required DateTime date, required DateTime time}) =>
|
||||||
|
'${_getDay(date)} ${Jiffy(time.toLocal()).format('HH:mm')}에 보냈습니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get todayLabel => '오늘';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get yesterdayLabel => '어제';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get channelIsMutedText => '채널이 음소거됩니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get noTitleText => '제목이 없습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get letsStartChattingLabel => '채팅 시작해요!';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendingFirstMessageLabel => '친구에게 첫 메시지를 보내 볼까요?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get startAChatLabel => '대화를 시작합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get loadingChannelsError => '채널을 로드하는 동안 오류가 발생했습니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteConversationLabel => '대화를 삭제합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get deleteConversationQuestion => '대화를 삭제하시겠습니까?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get streamChatLabel => '스트림 채팅';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get searchingForNetworkText => '네트워크를 검색하는 중입니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get offlineLabel => '오프라인...';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get tryAgainLabel => '다시 시도합니다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String membersCountText(int count) => '$count명';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String watchersCountText(int count) => '$count명이 온라인';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get viewInfoLabel => '정보를 보기';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveGroupLabel => '그룹을 떠납니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveLabel => '떠나다';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveConversationLabel => '대화에서 떠납니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get leaveConversationQuestion => '정말 이 대화에서 나가시겠습니까?';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get showInChatLabel => '채팅에 표시합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get saveImageLabel => '이미지를 저장합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get saveVideoLabel => '비디오를 저장합니다.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uploadErrorLabel => '업로드 오류';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get giphyLabel => '지피';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get shuffleLabel => '섞기';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get sendLabel => '보내기';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get withText => '함께';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get inText => '에';
|
||||||
|
|
||||||
|
// This is the word for 'customer' or 'user' because saying 'you' directly
|
||||||
|
// is too informal and rude
|
||||||
|
@override
|
||||||
|
String get youText => '당신';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String galleryPaginationText(
|
||||||
|
{required int currentPage, required int totalPages}) =>
|
||||||
|
'${currentPage + 1} / $totalPages';
|
||||||
|
//3 / 11
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get fileText => '파일';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get replyToMessageLabel => '메시지에 회신합니다.';
|
||||||
|
}
|
||||||
@@ -174,7 +174,7 @@ void main() {
|
|||||||
expect(localizations.withText, isNotNull);
|
expect(localizations.withText, isNotNull);
|
||||||
expect(localizations.inText, isNotNull);
|
expect(localizations.inText, isNotNull);
|
||||||
expect(localizations.youText, isNotNull);
|
expect(localizations.youText, isNotNull);
|
||||||
expect(localizations.ofText, isNotNull);
|
expect(localizations.galleryPaginationText, isNotNull);
|
||||||
expect(localizations.fileText, isNotNull);
|
expect(localizations.fileText, isNotNull);
|
||||||
expect(localizations.replyToMessageLabel, isNotNull);
|
expect(localizations.replyToMessageLabel, isNotNull);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user