diff --git a/telegram-adium/TelegramAccountView.xib b/telegram-adium/TelegramAccountView.xib index e510fff..8f846a4 100644 --- a/telegram-adium/TelegramAccountView.xib +++ b/telegram-adium/TelegramAccountView.xib @@ -1,5 +1,5 @@ - + diff --git a/telegram-adium/TelegramAccountViewController.m b/telegram-adium/TelegramAccountViewController.m index 4efb68e..c2826c9 100644 --- a/telegram-adium/TelegramAccountViewController.m +++ b/telegram-adium/TelegramAccountViewController.m @@ -22,7 +22,7 @@ #import #import #import -#import DISPLAY +#import #include "telegram-purple.h" diff --git a/telegram-adium/TelegramAutocompletionDelegate.h b/telegram-adium/TelegramAutocompletionDelegate.h new file mode 100644 index 0000000..87b216a --- /dev/null +++ b/telegram-adium/TelegramAutocompletionDelegate.h @@ -0,0 +1,28 @@ +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + * Copyright Matthias Jentsch 2014-2015 + */ + +#import + +#include + +@interface TelegramAutocompletionDelegate : NSObject { + @private + struct tgl_state *TLS; +} +- (void)setTLS:(struct tgl_state *)TLS; +@end \ No newline at end of file diff --git a/telegram-adium/TelegramAutocompletionDelegate.m b/telegram-adium/TelegramAutocompletionDelegate.m new file mode 100644 index 0000000..3e74ada --- /dev/null +++ b/telegram-adium/TelegramAutocompletionDelegate.m @@ -0,0 +1,62 @@ +/** + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + * + * Copyright Matthias Jentsch 2014-2015 + */ + +#import + +#import "TelegramAutocompletionDelegate.h" + +@implementation TelegramAutocompletionDelegate + +- (NSArray *)tokenField:(NSTokenField *)tokenField +completionsForSubstring:(NSString *)substring + indexOfToken:(NSInteger)tokenIndex + indexOfSelectedItem:(NSInteger *)selectedIndex +{ + NSMutableArray *matchingUsers = [NSMutableArray new]; + const char *startsWith = [substring UTF8String]; + if (TLS) { + int i = 0; + while (i != -1) { + char *R = NULL; + i = tgl_complete_user_list (TLS, i, startsWith, (int) strlen(startsWith), &R); + if (R) { + [matchingUsers addObject: [[NSString alloc] initWithUTF8String:R]]; + } + } + } + return matchingUsers; +} + +- (id)tokenField:(NSTokenField *)tokenField +representedObjectForEditingString:(NSString *)editingString +{ + return nil; +} + +- (NSString *)tokenField:(NSTokenField *)tokenField +displayStringForRepresentedObject:(id)representedObject +{ + return nil; +} + +- (void)setTLS:(struct tgl_state *)_TLS +{ + TLS = _TLS; +} + +@end \ No newline at end of file diff --git a/telegram-adium/TelegramJoinChatView.xib b/telegram-adium/TelegramJoinChatView.xib index c1bf91c..57728bd 100644 --- a/telegram-adium/TelegramJoinChatView.xib +++ b/telegram-adium/TelegramJoinChatView.xib @@ -1,24 +1,26 @@ - + - + + + - + - + @@ -26,15 +28,91 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/telegram-adium/TelegramJoinChatViewController.h b/telegram-adium/TelegramJoinChatViewController.h index 9b0e388..6d9c2f6 100644 --- a/telegram-adium/TelegramJoinChatViewController.h +++ b/telegram-adium/TelegramJoinChatViewController.h @@ -20,8 +20,10 @@ @class AIAccount, AICompletingTextField; -@interface TelegramJoinChatViewController : DCJoinChatViewController { +@interface TelegramJoinChatViewController : DCJoinChatViewController { IBOutlet NSPopUpButton *popupButton_existingChat; + IBOutlet NSTextField *textField_createChatName; + IBOutlet NSTokenField *tokenField_createChatUsers; } @end \ No newline at end of file diff --git a/telegram-adium/TelegramJoinChatViewController.m b/telegram-adium/TelegramJoinChatViewController.m index 72baffc..8fef673 100644 --- a/telegram-adium/TelegramJoinChatViewController.m +++ b/telegram-adium/TelegramJoinChatViewController.m @@ -17,10 +17,13 @@ */ #include -#include "TelegramJoinChatViewController.h" #include "telegram-purple.h" #include "tgp-structs.h" #include "tgp-chat.h" +#include "telegram-base.h" + +#include "TelegramJoinChatViewController.h" +#include "TelegramAutocompletionDelegate.h" #import #import @@ -67,32 +70,71 @@ static void tgl_peer_iterator_cb (tgl_peer_t *peer, void *extra) { [leftChats addObject: name]; } } - + NSArray *sortedChats = [chats sortedArrayUsingComparator:^NSComparisonResult(id a, id b) { return [(NSString*)a compare:b options:NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch]; }]; [popupButton_existingChat addItemsWithTitles: sortedChats]; - // TODO: Display left chats with a grey font to indicate that those are no // longer, but still allow the user to view the history // [popupButton_existingChat addItemsWithTitles: leftChats]; + + // provide the current TLS instance for access by the autocompletion + TelegramAutocompletionDelegate *D = [tokenField_createChatUsers delegate]; + if (D != nil) { + [D setTLS:conn->TLS]; + } } } - (void)joinChatWithAccount:(AIAccount *)inAccount { - NSString *room = [[popupButton_existingChat selectedItem] title]; - - NSDictionary *chatCreationInfo = [NSDictionary - dictionaryWithObjectsAndKeys:room, @"subject", nil]; - - [self doJoinChatWithName:room - onAccount:inAccount - chatCreationInfo:chatCreationInfo - invitingContacts:@[] - withInvitationMessage:@""]; + PurpleAccount *pa = [(CBPurpleAccount *)inAccount purpleAccount]; + PurpleConnection *gc = purple_account_get_connection(pa); + if (gc && PURPLE_CONNECTION_IS_CONNECTED(gc)) { + connection_data *conn = purple_connection_get_protocol_data (gc); + NSString *createChatName = [textField_createChatName stringValue]; + NSArray *tokens = [tokenField_createChatUsers objectValue]; + if ([createChatName length] && [tokens count]) { + int i, cnt = (int)[tokens count]; + const char **users = g_malloc(cnt * sizeof(char*)); + for (i = 0; i < cnt; i++) { + users[i] = [tokens[i] UTF8String]; + } + tgp_create_group_chat_by_usernames (conn->TLS, [createChatName UTF8String], users, i, TRUE); + g_free (users); + return; + } + /* + int i = 0; + tgl_peer_id_t ids[(int)[tokens count] + 1]; + ids[i++] = TGL_MK_USER(conn->TLS->our_id); + for (NSString *user in tokens) { + tgl_peer_t *P = NULL; + P = tgl_peer_get_by_name (conn->TLS, [user UTF8String]); + if (P) { + ids[i++] = P->id; + } + } + const char *subject = [createChatName UTF8String]; + tgl_do_create_group_chat(conn->TLS, i, ids, subject, (int) strlen(subject), + create_group_chat_done_cb, NULL); + // TODO: display new chat + return; + } + */ + + NSString *room = [[popupButton_existingChat selectedItem] title]; + NSDictionary *chatCreationInfo = [NSDictionary + dictionaryWithObjectsAndKeys:room, @"subject", nil]; + [self doJoinChatWithName:room + onAccount:inAccount + chatCreationInfo:chatCreationInfo + invitingContacts:@[] + withInvitationMessage:@""]; + } } - (NSString *)nibName @@ -100,5 +142,4 @@ static void tgl_peer_iterator_cb (tgl_peer_t *peer, void *extra) { return @"TelegramJoinChatView"; } - @end diff --git a/telegram-adium/TelegramPlugin.m b/telegram-adium/TelegramPlugin.m index e420bde..478a5f8 100644 --- a/telegram-adium/TelegramPlugin.m +++ b/telegram-adium/TelegramPlugin.m @@ -31,9 +31,9 @@ extern void purple_init_telegram_plugin(); - (void) installPlugin { - pk_path = [self getPkName]; - purple_init_telegram_plugin(); - [TelegramService registerService]; + pk_path = [self getPkName]; + purple_init_telegram_plugin(); + [TelegramService registerService]; } - (void) installLibpurplePlugin diff --git a/telegram-adium/telegram-adium.xcodeproj/project.pbxproj b/telegram-adium/telegram-adium.xcodeproj/project.pbxproj index ed018ca..f31bbed 100644 --- a/telegram-adium/telegram-adium.xcodeproj/project.pbxproj +++ b/telegram-adium/telegram-adium.xcodeproj/project.pbxproj @@ -44,6 +44,8 @@ C4D819061A5C862E0044CBA9 /* tgp-structs.c in Sources */ = {isa = PBXBuildFile; fileRef = C4D819041A5C862E0044CBA9 /* tgp-structs.c */; }; C4E528111A8A907200C4B915 /* tgp-ft.c in Sources */ = {isa = PBXBuildFile; fileRef = C4E5280F1A8A907200C4B915 /* tgp-ft.c */; }; C4EA965A1B204C67006CBAD0 /* libwebp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C4EA96591B204C67006CBAD0 /* libwebp.a */; }; + C4FFD0DC1B5FC48B00939D8A /* TelegramAutocompletionDelegate.h in Sources */ = {isa = PBXBuildFile; fileRef = C4FFD0DB1B5FC48B00939D8A /* TelegramAutocompletionDelegate.h */; }; + C4FFD0DE1B5FC68400939D8A /* TelegramAutocompletionDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C4FFD0DD1B5FC68400939D8A /* TelegramAutocompletionDelegate.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -122,6 +124,8 @@ C4E5280F1A8A907200C4B915 /* tgp-ft.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "tgp-ft.c"; path = "../tgp-ft.c"; sourceTree = ""; }; C4E528101A8A907200C4B915 /* tgp-ft.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "tgp-ft.h"; path = "../tgp-ft.h"; sourceTree = ""; }; C4EA96591B204C67006CBAD0 /* libwebp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebp.a; path = Frameworks/libwebp.a; sourceTree = ""; }; + C4FFD0DB1B5FC48B00939D8A /* TelegramAutocompletionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TelegramAutocompletionDelegate.h; sourceTree = ""; }; + C4FFD0DD1B5FC68400939D8A /* TelegramAutocompletionDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TelegramAutocompletionDelegate.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -149,6 +153,8 @@ C410947D19BB2D7D0083BF3F = { isa = PBXGroup; children = ( + C4FFD0DB1B5FC48B00939D8A /* TelegramAutocompletionDelegate.h */, + C4FFD0DD1B5FC68400939D8A /* TelegramAutocompletionDelegate.m */, C4B4BE321AB4536F0064AC17 /* PurpleDefaultsTelegram.plist */, C438CE251A12BEAF00E1DA0F /* telegram22.png */, C438CE231A12BEAF00E1DA0F /* telegram.png */, @@ -368,6 +374,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C4FFD0DC1B5FC48B00939D8A /* TelegramAutocompletionDelegate.h in Sources */, C438CE321A12C07800E1DA0F /* msglog.c in Sources */, C438CE351A12C07800E1DA0F /* tgp-net.c in Sources */, C438CE331A12C07800E1DA0F /* telegram-base.c in Sources */, @@ -375,6 +382,7 @@ C438CE341A12C07800E1DA0F /* telegram-purple.c in Sources */, C4877C1819BB37EA006FA91F /* TelegramService.m in Sources */, C448ADA71AB0789A001B7ECD /* tgp-msg.c in Sources */, + C4FFD0DE1B5FC68400939D8A /* TelegramAutocompletionDelegate.m in Sources */, C4E528111A8A907200C4B915 /* tgp-ft.c in Sources */, C438CE361A12C07800E1DA0F /* tgp-timers.c in Sources */, C410949B19BB337A0083BF3F /* TelegramPlugin.m in Sources */, diff --git a/telegram-base.c b/telegram-base.c index feeda13..85a011c 100644 --- a/telegram-base.c +++ b/telegram-base.c @@ -614,49 +614,53 @@ void request_accept_secret_chat (struct tgl_state *TLS, struct tgl_secret_chat * g_free (message); } -static void create_group_chat_done_cb (struct tgl_state *TLS, void *_, int success) { +void create_group_chat_done_cb (struct tgl_state *TLS, void *title, int success) { if (! success) { // alert purple_notify_error (_telegram_protocol, "Creating Group Chat Failed", "Creating Group Chat Failed", "Check the error log for further information."); } + g_free (title); } -static const char* tgp_request_field_get_value_label (PurpleRequestFields *fields, const char *id) { - GList *labels = purple_request_field_choice_get_labels (purple_request_fields_get_field (fields, id)); - const char *value = g_list_nth_data(labels, purple_request_fields_get_choice(fields, id)); - debug ("Found choice: %s", value); - return value; +void tgp_create_group_chat_by_usernames (struct tgl_state *TLS, const char *title, + const char *users[], int num_users, int print_names) { + tgl_peer_id_t ids[num_users + 1]; + int i, j = 0; + ids[j++] = TGL_MK_USER(TLS->our_id); + for (i = 0; i < num_users; i++) if (str_not_empty(users[i])) { + tgl_peer_t *P = NULL; + if (print_names) { + P = tgl_peer_get_by_name (TLS, users[i]); + } else { + P = tgl_peer_get (TLS, TGL_MK_USER(atoi (users[i]))); + } + if (P && tgl_get_peer_id (P->id) != TLS->our_id) { + ids[j++] = P->id; + } else { + debug("User %s not found in peer list", users[j]); + } + } + if (i > 1) { + tgl_do_create_group_chat (TLS, i, ids, title, (int) strlen(title), + create_group_chat_done_cb, g_strdup (title)); + } else { + purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, + "Group not created", "Not enough users selected", + NULL, NULL, NULL); + } } static void create_group_chat_cb (void *_data, PurpleRequestFields* fields) { debug ("create_group_chat_cb()"); struct accept_create_chat_data *data = _data; const char *users[3] = { - tgp_request_field_get_value_label (fields, "user1"), - tgp_request_field_get_value_label (fields, "user2"), - tgp_request_field_get_value_label (fields, "user3") + purple_request_fields_get_string(fields, "user1"), + purple_request_fields_get_string(fields, "user2"), + purple_request_fields_get_string(fields, "user3") }; - tgl_peer_id_t ids[4]; - ids[0] = TGL_MK_USER(data->TLS->our_id); - int i = 1; - for (int j = 0; j < 3; j++) { - tgl_peer_t *P = NULL; - if ((P = tgl_peer_get_by_name (data->TLS, users[j])) && tgl_get_peer_id(P->id) != data->TLS->our_id) { - ids[i++] = P->id; - debug("adding user id: %d", tgl_get_peer_id(P->id)); - } else { - debug("User %s not found in peer list", users[j]); - } - } - if (i > 1) { - tgl_do_create_group_chat (data->TLS, i, ids, data->title, (int) strlen(data->title), - create_group_chat_done_cb, NULL); - } else { - purple_notify_message (_telegram_protocol, PURPLE_NOTIFY_MSG_INFO, - "Group not created", "Not enough users selected", - NULL, NULL, NULL); - } + + tgp_create_group_chat_by_usernames (data->TLS, data->title, users, 3, FALSE); g_free (data->title); free (data); } @@ -669,6 +673,7 @@ static void cancel_group_chat_cb (gpointer data) { free (d); } +/* static void create_user_list_entry (tgl_peer_t *P, void *extra) { GList **list = extra; if (tgl_get_peer_type (P->id) == TGL_PEER_USER) { @@ -691,6 +696,7 @@ static PurpleRequestField *create_user_list (struct tgl_state *TLS, const char * g_list_free(list); return field; } + */ void request_choose_user (struct accept_create_chat_data *data) { struct tgl_state *TLS = data->TLS; @@ -700,14 +706,24 @@ void request_choose_user (struct accept_create_chat_data *data) { // the user to specify at least one other one. PurpleRequestFields* fields = purple_request_fields_new(); PurpleRequestFieldGroup* group = purple_request_field_group_new ( - "Invite at least one other user. You can always add more users later..."); - purple_request_field_group_add_field (group, create_user_list (TLS, "user1", "User 1", 0)); - purple_request_field_group_add_field (group, create_user_list (TLS, "user2", "User 2", 1)); - purple_request_field_group_add_field (group, create_user_list (TLS, "user3", "User 3", 1)); + "Use the autocompletion to invite at least one additional user. You can always add more users once the chat was created..."); + + PurpleRequestField *field = purple_request_field_string_new("user1", "User Name", NULL, FALSE); + purple_request_field_set_type_hint (field, "screenname"); + purple_request_field_group_add_field (group, field); + + field = purple_request_field_string_new("user2", "User Name", NULL, FALSE); + purple_request_field_set_type_hint (field, "screenname"); + purple_request_field_group_add_field (group, field); + + field = purple_request_field_string_new("user3", "User Name", NULL, FALSE); + purple_request_field_set_type_hint (field, "screenname"); + purple_request_field_group_add_field (group, field); + purple_request_fields_add_group(fields, group); - purple_request_fields (conn->gc, "Create Groupe", "Invite Users", NULL, fields, + purple_request_fields (conn->gc, "Create Group", "Invite Users", NULL, fields, "Ok", G_CALLBACK(create_group_chat_cb), "Cancel", - G_CALLBACK(cancel_group_chat_cb), NULL, NULL, NULL, data); + G_CALLBACK(cancel_group_chat_cb), conn->pa, NULL, NULL, data); } void request_create_chat (struct tgl_state *TLS, const char *subject) { diff --git a/telegram-base.h b/telegram-base.h index d7af3eb..e74cf26 100644 --- a/telegram-base.h +++ b/telegram-base.h @@ -50,5 +50,7 @@ gchar *get_download_dir (struct tgl_state *TLS); void assert_file_exists (PurpleConnection *gc, const char *filepath, const char *format); int tgp_visualize_key(struct tgl_state *TLS, unsigned char* sha1_key); +void tgp_create_group_chat_by_usernames (struct tgl_state *TLS, const char *title, + const char *users[], int num_users, int print_names); #endif