diff --git a/android/app/src/main/java/com/helloworld/CoreModule.java b/android/app/src/main/java/com/helloworld/CoreModule.java index 0502af5..6e6827e 100644 --- a/android/app/src/main/java/com/helloworld/CoreModule.java +++ b/android/app/src/main/java/com/helloworld/CoreModule.java @@ -370,12 +370,12 @@ public void run() { } @ReactMethod - public void addContact(String id, String name, Promise promise) { + public void putContact(String id, String name, Promise promise) { new Thread(new Runnable() { @Override public void run() { try { - Boolean res = cService.addContact(id, name); + Boolean res = cService.putContact(id, name); promise.resolve(res); } catch (Exception e) { promise.reject(e); @@ -385,6 +385,20 @@ public void run() { } + @ReactMethod + public void seen(String id) { + new Thread(new Runnable() { + @Override + public void run() { + try { + cService.seen(id); + } catch (Exception e) {} + } + }).start(); + + } + + @Override public void onHostResume() { // Activity `onResume` diff --git a/android/core/src/main/aidl/fx/android/core/ICoreService.aidl b/android/core/src/main/aidl/fx/android/core/ICoreService.aidl index 467049d..74f0fe8 100644 --- a/android/core/src/main/aidl/fx/android/core/ICoreService.aidl +++ b/android/core/src/main/aidl/fx/android/core/ICoreService.aidl @@ -20,7 +20,7 @@ interface ICoreService { /** * add new contact */ - boolean addContact(String id, String name); + boolean putContact(String id, String name); /** * get contact info */ @@ -62,6 +62,10 @@ interface ICoreService { */ String sendMessage(String chatID, String text); /** + * seen recived messages + */ + oneway void seen(String chatID); + /** * Often you want to allow a service to call back to its clients. * This shows how to do so, by registering a callback interface with * the service. diff --git a/android/core/src/main/java/fx/android/core/CoreService.java b/android/core/src/main/java/fx/android/core/CoreService.java index 8e86151..97180aa 100644 --- a/android/core/src/main/java/fx/android/core/CoreService.java +++ b/android/core/src/main/java/fx/android/core/CoreService.java @@ -273,9 +273,9 @@ public String getChats(int skip, int limit) throws RemoteException { } } - public boolean addContact(String id, String name) throws RemoteException { + public boolean putContact(String id, String name) throws RemoteException { try { - core.addContact(id, name); + core.putContact(id, name); return true; } catch (Exception e) { return handleCoreException(false, e, "can not add contact"); @@ -308,7 +308,9 @@ public String getIdentity() throws RemoteException { public String newIdentity(String name) throws RemoteException { try { - return core.newIdentity(name); + String identity = core.newIdentity(name); + core.start(); + return identity; } catch (Exception e) { return handleCoreException(null, e, "failed to retrieve create identity"); } @@ -356,13 +358,19 @@ public String getPMChat(String contactID) throws RemoteException { } public String sendMessage(String chatID, String text) throws RemoteException { - Log.d(NAME, "send called"); + Log.d(NAME, "send called with: "+chatID +", " +text ); try { return core.sendMessage(chatID, text); } catch (Exception e) { return handleCoreException(null, e, "failed to send private message"); } } + + public void seen(String chatID) throws RemoteException { + try { + core.seen(chatID); + } catch (Exception e) { } + } }; } \ No newline at end of file diff --git a/app/components/chat/MessageStatus.tsx b/app/components/chat/MessageStatus.tsx index 6768632..8ec0d65 100644 --- a/app/components/chat/MessageStatus.tsx +++ b/app/components/chat/MessageStatus.tsx @@ -7,7 +7,7 @@ interface Props { id : string } export const MessageStatus: FC= observer((props: Props) => { - const { chatStore: { messages } } = useStores() + const { messageStore: { messages } } = useStores() const msg = messages.get(props.id) return( diff --git a/app/models/Chat.ts b/app/models/Chat.ts index 4039263..c1235bf 100644 --- a/app/models/Chat.ts +++ b/app/models/Chat.ts @@ -1,6 +1,5 @@ import { Instance, SnapshotIn, SnapshotOut, types } from "mobx-state-tree" import { ContactModel } from "./Contact" -import { MessageModel } from "./Message" /** * Model description here for TypeScript hints. @@ -11,6 +10,9 @@ export const ChatModel = types _id: types.identifier, name: types.string, members: types.array(types.reference(ContactModel)), + type: types.integer, + unread: types.integer, + latestText: types.string }) .views((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars .actions((self) => ({})) // eslint-disable-line @typescript-eslint/no-unused-vars diff --git a/app/models/ChatStore.ts b/app/models/ChatStore.ts index 118d7df..2819537 100644 --- a/app/models/ChatStore.ts +++ b/app/models/ChatStore.ts @@ -12,15 +12,10 @@ export const ChatStoreModel = types .props({ chats: types.map(ChatModel), selected: types.maybeNull(types.reference(ChatModel)), - messages: types.map(MessageModel), - hasEarlierMessages: types.maybe(types.boolean) }) .views((self) => ({ get chatList() { return self.chats.values() - }, - get sortedMessages() { - return [...self.messages.values()].sort((a, b) => b.createdAt - a.createdAt) } })) // eslint-disable-line @typescript-eslint/no-unused-vars .actions((self) => { @@ -36,11 +31,10 @@ export const ChatStoreModel = types self.chats.put(chat) } - selectChat(chat._id) - + select(chat._id) }) - const loadChatList = flow(function* loadChatList() { - const list = yield api.beeCore.chat.list(0, 50) + const load = flow(function* loadChatList() { + const list = yield api.beeCore.chat.list(0, 0) const root = getRootStore(self) const members = list.flatMap(item => item.members).filter((i)=>i !== root.identityStore.user._id) root.contactStore.load(members) @@ -48,35 +42,14 @@ export const ChatStoreModel = types self.chats.put(chat) }); }) - const selectChat = flow(function* selectChat(chatId: string) { + const select = flow(function* selectChat(chatId: string) { const selected = self.chats.get(chatId) if (self.selected == null || self.selected._id !== selected._id) { self.selected = selected - self.hasEarlierMessages = true - self.messages.clear() } - - }) - const loadMessages = flow(function* loadMessages() { - const messages: Message[] = yield api.beeCore.messages.list(self.selected._id, self.messages.size, self.messages.size + 20) - self.hasEarlierMessages = !(messages.length < 20); - messages.forEach(msg => { - self.messages.put(msg) - }); - }) - const send = flow(function* send(msg: Message) { - let rmsg: Message = yield api.beeCore.chat.send(self.selected._id, { - _id: msg._id, - chatId: "", - createdAt: msg.createdAt, - user: msg.user._id, - text: msg.text - }) - self.messages.put(rmsg) }) const clear = () => { self.selected = null - self.messages.clear() } const onMessageChange = flow(function* onMessageChange(id: string, action: string) { //Todo: to much if and else need to clean it up @@ -85,38 +58,25 @@ export const ChatStoreModel = types switch (action) { case "received": let rmsg: Message = yield api.beeCore.messages.get(id) - // Chat if chat open put message - if (self.selected && self.selected._id === rmsg.chatId) { - self.messages.put(rmsg) - } // Add chat to list if not exist if (!self.chats.has(rmsg.chatId)) { const root = getRootStore(self) let newCH = yield api.beeCore.chat.get(rmsg.chatId) root.contactStore.load(newCH.members) self.chats.put(newCH); + } else { + const chat = self.chats.get(rmsg.chatId) + chat.latestText = rmsg.text + chat.unread += 1 + } break; - case "sent": - let smsg = self.messages.get(id) - if (self.selected && smsg && self.selected._id === smsg.chatId ) { - smsg.onSent() - } - break; - case "failed": - let nmsg = self.messages.get(id) - if (self.selected && nmsg && self.selected._id === nmsg.chatId) { - nmsg.onFailed() - } - break; } }) return { - loadMessages, openPMChat, - selectChat, - loadChatList, - send, + select, + load, clear, onMessageChange } diff --git a/app/models/ContactStore.ts b/app/models/ContactStore.ts index 76a88fb..6cfd85d 100644 --- a/app/models/ContactStore.ts +++ b/app/models/ContactStore.ts @@ -43,7 +43,7 @@ export const ContactStoreModel = types self.form.saving = true; const newContact = { _id:self.form._id, name:self.form.name } try { - const res = yield api.beeCore.contact.add(newContact) + const res = yield api.beeCore.contact.put(newContact) if(res){ self.contacts.put(newContact) }else{ diff --git a/app/models/Message.ts b/app/models/Message.ts index b1aa2c1..6ad9ce0 100644 --- a/app/models/Message.ts +++ b/app/models/Message.ts @@ -14,6 +14,7 @@ export const MessageModel = types chatId: types.string, user: types.reference(ContactModel), sent: types.maybe(types.boolean), + seen: types.maybe(types.boolean), received: types.maybe(types.boolean), pending: types.maybe(types.boolean), failed: types.maybe(types.boolean), diff --git a/app/models/MessageStore.ts b/app/models/MessageStore.ts new file mode 100644 index 0000000..c7e42a6 --- /dev/null +++ b/app/models/MessageStore.ts @@ -0,0 +1,113 @@ +import { flow, Instance, SnapshotIn, SnapshotOut, types } from "mobx-state-tree" +import { api } from "../services/core" +import { Message, MessageModel } from "./Message" +import { getRootStore } from "./helpers/getRootStore" +import { getUnixTime } from "date-fns" + +const PAGINATION_SIZE = 20 +const REFRESH_SIZE = 5 + +/** + * Model description here for TypeScript hints. + */ +export const MessageStoreModel = types + .model("MessageStore") + .props({ + messages: types.map(MessageModel), + hasEarlierMessages: types.maybe(types.boolean), + chatId: types.maybeNull(types.string), + block: types.maybeNull(types.number) + }) + .views((self) => ({ + get sortedMessages() { + return [...self.messages.values()].sort((a, b) => b.createdAt - a.createdAt) + } + })) // eslint-disable-line @typescript-eslint/no-unused-vars + .actions((self) => { + const onFocus = flow(function* onFocus() { + if(self.block+1000< getUnixTime(new Date())){ + refresh() + self.block=getUnixTime(new Date()) + } + // check chat is selected + api.beeCore.chat.seen(self.chatId) + }) + const open = flow(function* open(chatId) { + if(self.chatId !== chatId){ + self.chatId = chatId + self.block = getUnixTime(new Date()) + clear() + load() + } + }) + const refresh = flow(function* refresh() { + let skip = 0 + let limit = self.messages.size > 0 ? PAGINATION_SIZE : REFRESH_SIZE + const messages: Message[] = yield api.beeCore.messages.list(self.chatId, skip, limit) + self.hasEarlierMessages = !(messages.length < 20); + messages.forEach(msg => { + self.messages.put(msg) + }); + }) + const load = flow(function* load() { + const messages: Message[] = yield api.beeCore.messages.list(self.chatId, self.messages.size, self.messages.size + PAGINATION_SIZE) + self.hasEarlierMessages = !(messages.length < 20); + messages.forEach(msg => { + self.messages.put(msg) + }); + }) + const send = flow(function* send(msg: Message) { + let rmsg: Message = yield api.beeCore.chat.send(self.chatId, { + _id: msg._id, + chatId: "", + createdAt: msg.createdAt, + user: msg.user._id, + text: msg.text + }) + self.messages.put(rmsg) + }) + const clear = () => { + self.messages.clear() + self.hasEarlierMessages = false + } + const onMessageChange = flow(function* onMessageChange(id: string, action: string) { + //Todo: to much if and else need to clean it up + console.log("update message called with ", id, action) + // New Received Message + switch (action) { + case "received": + let rmsg: Message = yield api.beeCore.messages.get(id) + // Chat if chat open put message + if (self.chatId && self.chatId === rmsg.chatId) { + self.messages.put(rmsg) + } + break; + case "sent": + let smsg = self.messages.get(id) + if (self.chatId && smsg && self.chatId === smsg.chatId) { + smsg.onSent() + } + break; + case "failed": + let nmsg = self.messages.get(id) + if (self.chatId && nmsg && self.chatId === nmsg.chatId) { + nmsg.onFailed() + } + break; + } + }) + return { + onFocus, + refresh, + load, + send, + clear, + open, + onMessageChange + } + }) // eslint-disable-line @typescript-eslint/no-unused-vars + +export interface MessageStore extends Instance { } +export interface MessageStoreSnapshotOut extends SnapshotOut { } +export interface MessageStoreSnapshotIn extends SnapshotIn { } +export const createMessageStoreDefaultModel = () => types.optional(MessageStoreModel, {}) diff --git a/app/models/RootStore.ts b/app/models/RootStore.ts index a62d8d4..b0ae3e9 100644 --- a/app/models/RootStore.ts +++ b/app/models/RootStore.ts @@ -3,6 +3,7 @@ import { createContactStoreDefaultModel } from "./ContactStore" import { createChatListDefaultModel } from "./ChatStore" import { createIdentityDefaultModel } from "./Identity" import { createPermissionsDefaultModel } from "./Permissions" +import { createMessageStoreDefaultModel } from "./MessageStore" /** * A RootStore model. @@ -11,7 +12,8 @@ export const RootStoreModel = types.model("RootStore").props({ contactStore: createContactStoreDefaultModel(), identityStore: createIdentityDefaultModel(), chatStore: createChatListDefaultModel(), - permissionStore: createPermissionsDefaultModel() + permissionStore: createPermissionsDefaultModel(), + messageStore: createMessageStoreDefaultModel(), }) /** diff --git a/app/models/index.ts b/app/models/index.ts index 0298710..5f4a600 100644 --- a/app/models/index.ts +++ b/app/models/index.ts @@ -7,6 +7,7 @@ export * from "./Chat" export * from "./Contact" export * from "./Message" export * from "./ChatStore" +export * from "./MessageStore" export * from "./NewContact" export * from "./ContactStore" export * from "./Permissions" diff --git a/app/screens/ChatListScreen.tsx b/app/screens/ChatListScreen.tsx index f177065..af29478 100644 --- a/app/screens/ChatListScreen.tsx +++ b/app/screens/ChatListScreen.tsx @@ -1,17 +1,18 @@ -import React, { FC, useEffect } from "react" -import { FlatList, Platform, View } from 'react-native'; -import { observer } from "mobx-react-lite" +import React, { FC, useCallback, useEffect } from "react" +import { FlatList, Platform, TextStyle, View } from 'react-native'; +import { Observer, observer } from "mobx-react-lite" import { ViewStyle } from "react-native" import { StackScreenProps } from "@react-navigation/stack" import { ChatScreenProps } from "../navigators" import { Screen } from "../components" import { useFocusEffect, useNavigation } from "@react-navigation/native" import { useStores } from "../models" -import { Appbar, FAB, Menu } from 'react-native-paper'; +import { Appbar, Avatar, Badge, FAB, Menu } from 'react-native-paper'; import { List } from 'react-native-paper'; import Clipboard from '@react-native-clipboard/clipboard'; import { HeaderButtonProps } from "@react-navigation/native-stack/lib/typescript/src/types"; import coreSync from "../models/helpers/coreSync"; +import { spacing } from "../theme"; const MORE_ICON = Platform.OS === 'ios' ? 'dots-horizontal' : 'dots-vertical'; @@ -46,19 +47,21 @@ export const ChatListHeaderMenu = (_props: HeaderButtonProps) => { export const ChatListScreen: FC>> = observer(function ChatListScreen() { // Pull in one of our MST stores - const { chatStore } = useStores() + const { chatStore,messageStore } = useStores() // Pull in navigation via hook const navigation = useNavigation() - useFocusEffect(() => { - chatStore.loadChatList() + + useFocusEffect(useCallback(()=>{ + chatStore.load() const sub = coreSync(chatStore) return () => sub.remove() - }); + },[])) const navigateItem = (id) => { return () => { - chatStore.selectChat(id) + // chatStore.select(id) + messageStore.open(id) navigation.navigate("Chat") } } @@ -70,8 +73,13 @@ export const ChatListScreen: FC>> = const renderItem = ({ item }) => ( + titleStyle={$listItemTitle} + description={item.latestText} + onPress={navigateItem(item._id)} + left={props => } + right={props => {()=>item.unread>0&&{item.unread}}} /> ) return ( @@ -121,4 +129,19 @@ const $fixedView: ViewStyle = { bottom: 0, flexDirection: 'row', justifyContent: 'flex-end', +} + +const listItem: ViewStyle = { + marginLeft: spacing.small, + marginRight: 0, + paddingRight: 0, +} + +const $listItemTitle: TextStyle = { + fontSize:18 +} + +const $badgeContainer: ViewStyle = { + display: "flex", + justifyContent: "center" } \ No newline at end of file diff --git a/app/screens/ChatScreen.tsx b/app/screens/ChatScreen.tsx index b7ec9be..05d2813 100644 --- a/app/screens/ChatScreen.tsx +++ b/app/screens/ChatScreen.tsx @@ -1,4 +1,4 @@ -import React, { FC, useEffect } from "react" +import React, { FC, useCallback, useEffect } from "react" import { observer } from "mobx-react-lite" import { StackScreenProps } from "@react-navigation/stack" import { ChatScreenProps } from "../navigators" @@ -11,29 +11,38 @@ import { useFocusEffect, useNavigation } from "@react-navigation/native" export const ChatScreen: FC>> = observer(function ChatScreen() { // Pull in one of our MST stores - const { chatStore: {selected,sortedMessages, send, loadMessages, hasEarlierMessages} , identityStore } = useStores() + const { messageStore: { onFocus, chatId }} = useStores() const rootStore = useStores() const navigation = useNavigation() useFocusEffect(()=>{ - if(selected == null){ - navigation.navigate("ChatList"); + if(chatId){ + onFocus() + console.log("onFocus") + const sub = coreSync(rootStore.messageStore) + return () => sub.remove() } else { - loadMessages() - const sub = coreSync(rootStore.chatStore) - return ()=>sub.remove() + navigation.navigate("ChatList") } - }); + }) + + return ( + + ) +}) + +export const Chat = observer(function Chat() { + const { messageStore: { send, load, hasEarlierMessages, sortedMessages }, identityStore } = useStores() return ( { - messages.map(msg=>send(msg)) + messages.map(msg => send(msg)) }} user={identityStore.user} loadEarlier={hasEarlierMessages} - onLoadEarlier={loadMessages} + onLoadEarlier={load} infiniteScroll={true} /> ) diff --git a/app/services/core/real/beeCore.ts b/app/services/core/real/beeCore.ts index a2e8d0d..3defce0 100644 --- a/app/services/core/real/beeCore.ts +++ b/app/services/core/real/beeCore.ts @@ -19,6 +19,9 @@ import 'fastestsmallesttextencoderdecoder'; import { Buffer } from 'buffer'; class ChatAPI implements IChat { + seen(id: string): void { + CoreModule.seen(id) + } async get(id: ID): Promise { const res = await CoreModule.getChat(id.toString()) @@ -65,8 +68,8 @@ class ContactAPI implements IContact { const chat: Contact = base64ToObject(res) return chat } - async add(con: Contact): Promise { - const res = await CoreModule.addContact(con._id, con.name) + async put(con: Contact): Promise { + const res = await CoreModule.putContact(con._id, con.name) return res } async list(skip: number, limit: number): Promise { diff --git a/app/services/core/real/beeCore.type.ts b/app/services/core/real/beeCore.type.ts index 9c1c023..0d44734 100644 --- a/app/services/core/real/beeCore.type.ts +++ b/app/services/core/real/beeCore.type.ts @@ -16,6 +16,7 @@ export interface IChat { get(id: ID): Promise list(skip: number, limit: number): Promise send(id: ID, msg: Message): Promise + seen(id: ID): void } export interface IPrivateChat { @@ -31,7 +32,7 @@ export interface IMessages { export interface IContact { get(id: ID): Promise - add(con: Contact): Promise + put(con: Contact): Promise list(skip: number, limit: number): Promise } @@ -66,6 +67,9 @@ export interface Chat { _id: ID, name: string, members: ID[] + type: number, + unread: number, + latestText: string } export interface Message { diff --git a/go/bridge.go b/go/bridge.go index bfe1f40..d354eff 100644 --- a/go/bridge.go +++ b/go/bridge.go @@ -1,6 +1,7 @@ package bridge import ( + "errors" "strings" "github.com/hood-chat/core" @@ -13,7 +14,7 @@ import ( var log = logging.Logger("bridge") type Bridge struct { - core core.Messenger + core.MessengerAPI } func NewBridge(repoPath string, conf *HostConfig) (*Bridge, error) { @@ -25,7 +26,7 @@ func NewBridge(repoPath string, conf *HostConfig) (*Bridge, error) { panic("new hb failed") } - m := core.MessengerBuilder(repoPath, Option(), hb) + m := core.NewMessengerAPI(repoPath, Option(), hb) f := &Bridge{m} sub, err := m.EventBus().Subscribe(new(event.EvtObject)) @@ -45,7 +46,7 @@ func NewBridge(repoPath string, conf *HostConfig) (*Bridge, error) { } func (b *Bridge) IsLogin() bool { - return b.core.IsLogin() + return b.IdentityAPI().IsLogin() } func (b *Bridge) GetInterfaces() (string, error) { @@ -72,7 +73,7 @@ func (b *Bridge) GetInterfaces() (string, error) { } func (b *Bridge) GetIdentity() (string, error) { - idn, err := b.core.GetIdentity() + idn, err := b.IdentityAPI().Get() if err != nil { return "", err } @@ -81,7 +82,7 @@ func (b *Bridge) GetIdentity() (string, error) { } func (b *Bridge) NewIdentity(name string) (string, error) { - idn, err := b.core.SignUp(name) + idn, err := b.IdentityAPI().SignUp(name) if err != nil { return "", err } @@ -91,8 +92,7 @@ func (b *Bridge) NewIdentity(name string) (string, error) { func (b *Bridge) GetChat(id string) (string, error) { chatId := entity.ID(id) - msgr := b.core - ch, err := msgr.GetChat(chatId) + ch, err := b.ChatAPI().ChatInfo(chatId) if err != nil { return "", err } @@ -101,8 +101,7 @@ func (b *Bridge) GetChat(id string) (string, error) { } func (b *Bridge) GetChats(skip int, limit int) (string, error) { - msgr := b.core - ch, err := msgr.GetChats(skip, limit) + ch, err := b.ChatAPI().ChatInfos(skip, limit) if err != nil { return "", err } @@ -112,8 +111,7 @@ func (b *Bridge) GetChats(skip int, limit int) (string, error) { func (b *Bridge) GetMessages(chatID string, skip int, limit int) (string, error) { id := entity.ID(chatID) - msgr := b.core - msgs, err := msgr.GetMessages(id, skip, limit) + msgs, err := b.ChatAPI().Messages(id, skip, limit) if err != nil { return "", err } @@ -122,18 +120,16 @@ func (b *Bridge) GetMessages(chatID string, skip int, limit int) (string, error) } func (b *Bridge) GetMessageNotification(msgID string) (*Notification, error) { - msgr := b.core - msg, err := msgr.GetMessage(entity.ID(msgID)) + msg, err := b.ChatAPI().Message(entity.ID(msgID)) if err != nil { return nil, err } - return NewNotification(msg.Author.Name,msg.Text), nil + return NewNotification(msg.Author.Name, msg.Text), nil } func (b *Bridge) GetMessage(ID string) (string, error) { id := entity.ID(ID) - msgr := b.core - msg, err := msgr.GetMessage(id) + msg, err := b.ChatAPI().Message(entity.ID(id)) if err != nil { return "", err } @@ -142,8 +138,7 @@ func (b *Bridge) GetMessage(ID string) (string, error) { } func (b *Bridge) SendMessage(chatId string, text string) (string, error) { - msgr := b.core - msg, err := msgr.SendPM(entity.ID(chatId), text) + msg, err := b.ChatAPI().Send(entity.ID(chatId), text) if err != nil { return "", err } @@ -152,8 +147,7 @@ func (b *Bridge) SendMessage(chatId string, text string) (string, error) { } func (b *Bridge) GetContacts(skip int, limit int) (string, error) { - msgr := b.core - cs, err := msgr.GetContacts(skip, limit) + cs, err := b.ContactBookAPI().List(skip, limit) if err != nil { return "", err } @@ -163,8 +157,7 @@ func (b *Bridge) GetContacts(skip int, limit int) (string, error) { func (b *Bridge) GetContact(id string) (string, error) { contactID := entity.ID(id) - msgr := b.core - c, err := msgr.GetContact(contactID) + c, err := b.ContactBookAPI().Get(contactID) if err != nil { return "", err } @@ -172,19 +165,21 @@ func (b *Bridge) GetContact(id string) (string, error) { return res.Serialize() } -func (b *Bridge) AddContact(id string, name string) error { - msgr := b.core - err := msgr.AddContact(entity.Contact{ +func (b *Bridge) PutContact(id string, name string) error { + err := b.ContactBookAPI().Put(entity.Contact{ ID: entity.ID(id), Name: name, }) return err } +func (b *Bridge) Seen(chatID string) error { + return b.ChatAPI().Seen(entity.ID(chatID)) +} + func (b Bridge) NewPMChat(contactID string) (string, error) { id := entity.ID(contactID) - msgr := b.core - pm, err := msgr.CreatePMChat(id) + pm, err := b.ChatAPI().New(core.ForPrivateChat(id)) if err != nil { return "", err } @@ -194,15 +189,13 @@ func (b Bridge) NewPMChat(contactID string) (string, error) { func (b Bridge) GetPMChat(contactID string) (string, error) { id := entity.ID(contactID) - msgr := b.core - pm, err := msgr.GetPMChat(id) + pm, err := b.ChatAPI().Find(core.ForPrivateChat(id)) if err != nil { return "", err } - res := BChat(pm) + if len(pm) == 0 { + return "", errors.New("not found") + } + res := BChat(pm[0]) return res.Serialize() } - -func (b Bridge) Stop() { - b.core.Stop() -} diff --git a/go/bridge_test.go b/go/bridge_test.go index 7b78aab..5381035 100644 --- a/go/bridge_test.go +++ b/go/bridge_test.go @@ -11,7 +11,7 @@ func TestGetChats(t *testing.T) { br, err := NewBridge(t.TempDir(),conf) require.NoError(t, err) - br.core.SignUp("farhoud") - require.Equal(t, br.core.IsLogin(), true) + br.IdentityAPI().SignUp("farhoud") + require.Equal(t, br.IdentityAPI().IsLogin(), true) } diff --git a/go/cast.go b/go/cast.go index 39601c3..3971264 100644 --- a/go/cast.go +++ b/go/cast.go @@ -28,7 +28,8 @@ func (m *BMessage) cast() Message { CreatedAt: m.CreatedAt * 1000, ContactID: m.Author.ID.String(), Sent: m.Status == entity.Sent, - Received: m.Status == entity.Seen, + Seen: m.Status == entity.Seen, + Received: m.Status == entity.Received, Pending: m.Status == entity.Pending, Failed: m.Status == entity.Failed, } @@ -81,6 +82,9 @@ func (m *BChat) cast() Chat { ID: m.ID.String(), Name: m.Name, Members: mids, + Type: int(m.Type), + LatestText: m.LatestText, + Unread: int(m.Unread), } } diff --git a/go/types.go b/go/types.go index 3dc8043..97252e4 100644 --- a/go/types.go +++ b/go/types.go @@ -6,9 +6,12 @@ type Identity struct { } type Chat struct { - ID string `json:"_id"` - Name string `json:"name"` - Members []string `json:"members"` + ID string `json:"_id"` + Name string `json:"name"` + Members []string `json:"members"` + Type int `json:"type"` + Unread int `json:"unread"` + LatestText string `json:"latestText"` } type Message struct { @@ -21,6 +24,7 @@ type Message struct { Received bool `json:"received"` Pending bool `json:"pending"` Failed bool `json:"failed"` + Seen bool `json:"Seen"` } type Contact struct {