From 95efd214266a9f1acb6578134a674955d7fce638 Mon Sep 17 00:00:00 2001 From: David Sinclair Date: Mon, 20 Dec 2021 19:50:22 -0700 Subject: [PATCH 1/5] #1578 (support link) --- clients/ios/Classes/FeedsObjCViewController.m | 5 +++++ clients/ios/Resources/MainInterface.storyboard | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/clients/ios/Classes/FeedsObjCViewController.m b/clients/ios/Classes/FeedsObjCViewController.m index 5b75e9441..026dcde34 100644 --- a/clients/ios/Classes/FeedsObjCViewController.m +++ b/clients/ios/Classes/FeedsObjCViewController.m @@ -1019,6 +1019,11 @@ static NSArray *NewsBlurTopSectionNames; }]; } + [viewController addTitle:@"Support Forum" iconName:@"world.png" selectionShouldDismiss:YES handler:^{ + NSURL *url = [NSURL URLWithString:@"https://forum.newsblur.com"]; + [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; + }]; + [viewController addTitle:@"Logout" iconName:@"menu_icn_fetch_subscribers.png" selectionShouldDismiss:YES handler:^{ [self.appDelegate confirmLogout]; }]; diff --git a/clients/ios/Resources/MainInterface.storyboard b/clients/ios/Resources/MainInterface.storyboard index bf7c68435..70d7d013c 100644 --- a/clients/ios/Resources/MainInterface.storyboard +++ b/clients/ios/Resources/MainInterface.storyboard @@ -14,7 +14,7 @@ - + From a44e307c690d7f9fb7630625f61df1e6a6750f00 Mon Sep 17 00:00:00 2001 From: David Sinclair Date: Mon, 20 Dec 2021 20:40:43 -0700 Subject: [PATCH 2/5] #1540 (comfortable/compact feeds) --- clients/ios/Classes/FeedsObjCViewController.m | 13 ++++++++++++- clients/ios/Classes/MenuViewController.h | 1 + clients/ios/Classes/MenuViewController.m | 10 +++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clients/ios/Classes/FeedsObjCViewController.m b/clients/ios/Classes/FeedsObjCViewController.m index 026dcde34..930e76872 100644 --- a/clients/ios/Classes/FeedsObjCViewController.m +++ b/clients/ios/Classes/FeedsObjCViewController.m @@ -1046,6 +1046,14 @@ static NSArray *NewsBlurTopSectionNames; [self.appDelegate resizeFontSize]; }]; + preferenceKey = @"feed_list_spacing"; + titles = @[@"Compact", @"Comfortable"]; + values = @[@"compact", @"comfortable"]; + + [viewController addSegmentedControlWithTitles:titles values:values defaultValue:@"comfortable" preferenceKey:preferenceKey selectionShouldDismiss:YES handler:^(NSUInteger selectedIndex) { + [self reloadFeedTitlesTable]; + }]; + [viewController addThemeSegmentedControl]; UINavigationController *navController = self.navigationController; @@ -1587,7 +1595,10 @@ static NSArray *NewsBlurTopSectionNames; UIFontDescriptor *fontDescriptor = [self fontDescriptorUsingPreferredSize:UIFontTextStyleCaption1]; UIFont *font = [UIFont fontWithName:@"WhitneySSm-Medium" size:fontDescriptor.pointSize]; - return height + font.pointSize*2; + NSString *spacing = [[NSUserDefaults standardUserDefaults] objectForKey:@"feed_list_spacing"]; + NSInteger offset = [spacing isEqualToString:@"compact"] ? 6 : 0; + + return height + (font.pointSize * 2) - offset; } - (void)resetRowHeights { diff --git a/clients/ios/Classes/MenuViewController.h b/clients/ios/Classes/MenuViewController.h index d5c796633..8214d28a6 100644 --- a/clients/ios/Classes/MenuViewController.h +++ b/clients/ios/Classes/MenuViewController.h @@ -22,6 +22,7 @@ typedef void (^MenuItemSegmentedHandler)(NSUInteger selectedIndex); - (void)addTitle:(NSString *)title iconTemplateName:(NSString *)iconTemplateName selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemHandler)handler; - (void)addSegmentedControlWithTitles:(NSArray *)titles selectIndex:(NSUInteger)selectIndex selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemSegmentedHandler)handler; - (void)addSegmentedControlWithTitles:(NSArray *)titles values:(NSArray *)values preferenceKey:(NSString *)preferenceKey selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemSegmentedHandler)handler; +- (void)addSegmentedControlWithTitles:(NSArray *)titles values:(NSArray *)values defaultValue:(NSString *)defaultValue preferenceKey:(NSString *)preferenceKey selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemSegmentedHandler)handler; - (void)addThemeSegmentedControl; - (void)showFromNavigationController:(UINavigationController *)navigationController barButtonItem:(UIBarButtonItem *)barButtonItem; diff --git a/clients/ios/Classes/MenuViewController.m b/clients/ios/Classes/MenuViewController.m index 095d5b191..d56f26c57 100644 --- a/clients/ios/Classes/MenuViewController.m +++ b/clients/ios/Classes/MenuViewController.m @@ -106,11 +106,19 @@ NSString * const MenuHandler = @"handler"; } - (void)addSegmentedControlWithTitles:(NSArray *)titles values:(NSArray *)values preferenceKey:(NSString *)preferenceKey selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemSegmentedHandler)handler { + [self addSegmentedControlWithTitles:titles values:values defaultValue:nil preferenceKey:preferenceKey selectionShouldDismiss:selectionShouldDismiss handler:handler]; +} + +- (void)addSegmentedControlWithTitles:(NSArray *)titles values:(NSArray *)values defaultValue:(NSString *)defaultValue preferenceKey:(NSString *)preferenceKey selectionShouldDismiss:(BOOL)selectionShouldDismiss handler:(MenuItemSegmentedHandler)handler { NSUserDefaults *userPreferences = [NSUserDefaults standardUserDefaults]; id value = [userPreferences objectForKey:preferenceKey]; NSUInteger valueIndex = [values indexOfObject:value]; - if (valueIndex < 0) { + if (valueIndex == NSNotFound && defaultValue != nil) { + valueIndex = [values indexOfObject:defaultValue]; + } + + if (valueIndex == NSNotFound) { valueIndex = 0; } From 738bdda22055c4e568bf9c12aef1f7005ab3a023 Mon Sep 17 00:00:00 2001 From: David Sinclair Date: Mon, 20 Dec 2021 21:20:52 -0700 Subject: [PATCH 3/5] #1579 (focus changes) --- clients/ios/Classes/FeedDetailObjCViewController.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clients/ios/Classes/FeedDetailObjCViewController.m b/clients/ios/Classes/FeedDetailObjCViewController.m index baa1dbccd..f79c8fbd4 100644 --- a/clients/ios/Classes/FeedDetailObjCViewController.m +++ b/clients/ios/Classes/FeedDetailObjCViewController.m @@ -95,6 +95,9 @@ typedef NS_ENUM(NSUInteger, MarkReadShowMenu) self.storyTitlesTable.backgroundColor = UIColorFromRGB(0xf4f4f4); self.storyTitlesTable.separatorColor = UIColorFromRGB(0xE9E8E4); + if (@available(iOS 15.0, *)) { + self.storyTitlesTable.allowsFocus = NO; + } if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { self.storyTitlesTable.dragDelegate = self; self.storyTitlesTable.dragInteractionEnabled = YES; From 10c405c44e51d6fd3905c7fc7030e43b89ea80af Mon Sep 17 00:00:00 2001 From: David Sinclair Date: Thu, 23 Dec 2021 16:18:26 -0700 Subject: [PATCH 4/5] #1575 (subscribe to site in share sheet) --- clients/ios/Classes/FeedsObjCViewController.m | 1 + .../Base.lproj/MainInterface.storyboard | 16 +- .../Share Extension/ShareViewController.swift | 160 +++++++++++++----- .../Share Extension/ShareViewDelegate.swift | 62 ++++++- 4 files changed, 183 insertions(+), 56 deletions(-) diff --git a/clients/ios/Classes/FeedsObjCViewController.m b/clients/ios/Classes/FeedsObjCViewController.m index 930e76872..dc5b6fefd 100644 --- a/clients/ios/Classes/FeedsObjCViewController.m +++ b/clients/ios/Classes/FeedsObjCViewController.m @@ -579,6 +579,7 @@ static NSArray *NewsBlurTopSectionNames; [defaults setObject:[results objectForKey:@"share_ext_token"] forKey:@"share:token"]; [defaults setObject:self.appDelegate.url forKey:@"share:host"]; [defaults setObject:appDelegate.dictSavedStoryTags forKey:@"share:tags"]; + [defaults setObject:appDelegate.dictFoldersArray forKey:@"share:folders"]; [self validateWidgetFeedsForGroupDefaults:defaults usingResults:results]; [defaults synchronize]; diff --git a/clients/ios/Share Extension/Base.lproj/MainInterface.storyboard b/clients/ios/Share Extension/Base.lproj/MainInterface.storyboard index 755260a6c..1ad3f38c0 100644 --- a/clients/ios/Share Extension/Base.lproj/MainInterface.storyboard +++ b/clients/ios/Share Extension/Base.lproj/MainInterface.storyboard @@ -1,8 +1,9 @@ - + - + + @@ -36,10 +37,11 @@ - + + @@ -52,7 +54,7 @@ - + @@ -76,14 +78,14 @@ - + - + @@ -105,7 +107,7 @@ - + diff --git a/clients/ios/Share Extension/ShareViewController.swift b/clients/ios/Share Extension/ShareViewController.swift index 34005cbdf..b74ca6c58 100644 --- a/clients/ios/Share Extension/ShareViewController.swift +++ b/clients/ios/Share Extension/ShareViewController.swift @@ -28,9 +28,12 @@ class ShareViewController: UIViewController { /// Share publicly. case share + + /// Add site. + case add } - /// Whether we are saving the story privately or sharing publicly. + /// Whether we are saving the story privately, sharing publicly, or adding a site. var mode: Mode = .save /// Dictionary representation of a tag. @@ -60,6 +63,15 @@ class ShareViewController: UIViewController { /// User-entered comments, only used when sharing. var comments = "" + /// An array of folders, from the main app. + var folders = [String]() + + /// New folder name, only used when adding. + var newFolder = "" + + /// Index path of the selected folder. + var selectedFolderIndexPath = IndexPath(item: 0, section: 0) + /// Title of the item being shared. var itemTitle: String? = nil @@ -83,6 +95,12 @@ class ShareViewController: UIViewController { } } + if let foldersArray = prefs.object(forKey: "share:folders") as? [String] { + folders = foldersArray + + folders.removeAll { ["river_global", "river_blurblogs", "infrequent", "read_stories", "saved_searches", "saved_stories"].contains($0) } + } + updateSaveButtonState() NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil) @@ -90,13 +108,14 @@ class ShareViewController: UIViewController { } func updateSaveButtonState() { - if mode == .save { + switch mode { + case .save: if let rows = tableView.indexPathsForSelectedRows { navigationItem.rightBarButtonItem?.isEnabled = !rows.isEmpty } else { navigationItem.rightBarButtonItem?.isEnabled = false } - } else { + default: navigationItem.rightBarButtonItem?.isEnabled = true } } @@ -112,12 +131,16 @@ class ShareViewController: UIViewController { } @IBAction func newTagFieldChanged(_ sender: UITextField) { - newTag = sender.text ?? "" - - if newTag.isEmpty { - tableView.deselectRow(at: indexPathForNewTag, animated: false) - } else { - tableView.selectRow(at: indexPathForNewTag, animated: false, scrollPosition: .none) + if mode == .save { + newTag = sender.text ?? "" + + if newTag.isEmpty { + tableView.deselectRow(at: indexPathForNewTag, animated: false) + } else { + tableView.selectRow(at: indexPathForNewTag, animated: false, scrollPosition: .none) + } + } else if mode == .add { + newFolder = sender.text ?? "" } updateSaveButtonState() @@ -154,9 +177,17 @@ class ShareViewController: UIViewController { } @IBAction func changedMode(_ sender: Any) { - mode = modeSegmentedControl.selectedSegmentIndex == 0 ? .save : .share - - navigationItem.rightBarButtonItem?.title = mode == .save ? "Save" : "Share" + switch modeSegmentedControl.selectedSegmentIndex { + case 1: + mode = .share + navigationItem.rightBarButtonItem?.title = "Share" + case 2: + mode = .add + navigationItem.rightBarButtonItem?.title = "Add" + default: + mode = .save + navigationItem.rightBarButtonItem?.title = "Save" + } tableView.isEditing = mode == .save tableView.reloadData() @@ -231,52 +262,89 @@ private extension ShareViewController { } var requestPath: String { - return mode == .save ? "api/save_story" : "api/share_story" + switch mode { + case .share: + return "api/share_story" + case .save: + return "api/save_story" + case .add: + return "reader/add_url" + } } func encoded(_ string: String?) -> String { return string?.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? "" } - func postBody(url: URL?, text: String?) -> String { + func postSave(url: URL?, text: String?) -> String { let title = itemTitle let encodedURL = encoded(url?.absoluteString) let encodedTitle = encoded(title) let encodedContent = encoded(text) - if mode == .save { - let indexPaths = tableView.indexPathsForSelectedRows ?? [] - var selectedTagsArray = [String]() - - for index in 0.. String { + let title = itemTitle + let encodedURL = encoded(url?.absoluteString) + let encodedTitle = encoded(title) + let encodedContent = encoded(text) + + var comments = comments + + // Don't really need this stuff if I don't populate the comments from the title or text; leave for now just in case that is wanted. + if title != nil && comments == title { + comments = "" + } + + if text != nil && comments == text { + comments = "" + } + + let encodedComments = encoded(comments) + + let postBody = "story_url=\(encodedURL)&title=\(encodedTitle)&content=\(encodedContent)&comments=\(encodedComments)" + + return postBody + } + + func postAdd(url: URL?, text: String?) -> String { + let folder = folders[selectedFolderIndexPath.row] + let encodedFolder = encoded(folder) + let encodedURL = encoded(url?.absoluteString) + + var postBody = "folder=\(encodedFolder)&url=\(encodedURL)" + + if newFolder != "" { + postBody += "&new_folder=\(encoded(newFolder))" + } + + return postBody + } + + func postBody(url: URL?, text: String?) -> String { + switch mode { + case .save: + return postSave(url: url, text: text) + case .share: + return postShare(url: url, text: text) + case .add: + return postAdd(url: url, text: text) } } } diff --git a/clients/ios/Share Extension/ShareViewDelegate.swift b/clients/ios/Share Extension/ShareViewDelegate.swift index bb87b6a4c..a57f6d14c 100644 --- a/clients/ios/Share Extension/ShareViewDelegate.swift +++ b/clients/ios/Share Extension/ShareViewDelegate.swift @@ -14,6 +14,11 @@ class ShareViewDelegate: NSObject { extension ShareViewDelegate: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + if viewController.mode == .add, indexPath.section == 0 { + viewController.selectedFolderIndexPath = indexPath + tableView.reloadData() + } + viewController.updateSaveButtonState() } @@ -23,14 +28,37 @@ extension ShareViewDelegate: UITableViewDelegate { } extension ShareViewDelegate: UITableViewDataSource { - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - if viewController.mode == .save { - return viewController.tags.count + 1 + func numberOfSections(in tableView: UITableView) -> Int { + if viewController.mode == .add { + return 2 } else { return 1 } } + func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + if viewController.mode == .add, section == 1 { + return "Add new sub-folder:" + } else { + return nil + } + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch viewController.mode { + case .save: + return viewController.tags.count + 1 + case .share: + return 1 + case .add: + if section == 0 { + return viewController.folders.count + } else { + return 1 + } + } + } + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if viewController.mode == .save { if indexPath.item < viewController.tags.count { @@ -47,6 +75,34 @@ extension ShareViewDelegate: UITableViewDataSource { } cell.tagField.text = "" + cell.tagField.placeholder = "new tag" + + return cell + } + } else if viewController.mode == .add { + if indexPath.section == 0 { + guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveTagCell.reuseIdentifier, for: indexPath) as? ShareSaveTagCell else { + preconditionFailure("Expected to dequeue a ShareSaveTagCell") + } + + let components = viewController.folders[indexPath.item].components(separatedBy: " ▸ ") + + if components.first == "everything" { + cell.tagLabel.text = "🗃 Top Level" + } else { + cell.tagLabel.text = "\(String(repeating: " ", count: components.count))📁 \(components.last ?? "?")" + } + + cell.accessoryType = indexPath == viewController.selectedFolderIndexPath ? .checkmark : .none + + return cell + } else { + guard let cell = tableView.dequeueReusableCell(withIdentifier: ShareSaveNewCell.reuseIdentifier, for: indexPath) as? ShareSaveNewCell else { + preconditionFailure("Expected to dequeue a ShareSaveNewCell") + } + + cell.tagField.text = viewController.newFolder + cell.tagField.placeholder = "new folder title" return cell } From 5438b549554ff1a0b1baadeeab39efa00cdcfd91 Mon Sep 17 00:00:00 2001 From: Samuel Clay Date: Wed, 5 Jan 2022 12:30:44 -0500 Subject: [PATCH 5/5] Using discourse icon for support forum link on ios. #1578 --- clients/ios/Classes/FeedsObjCViewController.m | 2 +- clients/ios/NewsBlur.xcodeproj/project.pbxproj | 8 ++++++++ clients/ios/Resources/discourse.png | Bin 0 -> 495 bytes clients/ios/Resources/discourse@2x.png | Bin 0 -> 899 bytes 4 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 clients/ios/Resources/discourse.png create mode 100644 clients/ios/Resources/discourse@2x.png diff --git a/clients/ios/Classes/FeedsObjCViewController.m b/clients/ios/Classes/FeedsObjCViewController.m index dc5b6fefd..048493bc6 100644 --- a/clients/ios/Classes/FeedsObjCViewController.m +++ b/clients/ios/Classes/FeedsObjCViewController.m @@ -1020,7 +1020,7 @@ static NSArray *NewsBlurTopSectionNames; }]; } - [viewController addTitle:@"Support Forum" iconName:@"world.png" selectionShouldDismiss:YES handler:^{ + [viewController addTitle:@"Support Forum" iconName:@"discourse.png" selectionShouldDismiss:YES handler:^{ NSURL *url = [NSURL URLWithString:@"https://forum.newsblur.com"]; [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil]; }]; diff --git a/clients/ios/NewsBlur.xcodeproj/project.pbxproj b/clients/ios/NewsBlur.xcodeproj/project.pbxproj index ddfb6878c..93b20def6 100755 --- a/clients/ios/NewsBlur.xcodeproj/project.pbxproj +++ b/clients/ios/NewsBlur.xcodeproj/project.pbxproj @@ -336,6 +336,8 @@ FF22FE7616E557D80046165A /* toolbar_tall_background.png in Resources */ = {isa = PBXBuildFile; fileRef = FF22FE7416E557D80046165A /* toolbar_tall_background.png */; }; FF22FE7716E557D80046165A /* toolbar_tall_background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF22FE7516E557D80046165A /* toolbar_tall_background@2x.png */; }; FF265F12187B6D4F0080C332 /* fitvid.js in Resources */ = {isa = PBXBuildFile; fileRef = FF265F10187B6B230080C332 /* fitvid.js */; }; + FF28C5B8278603750033D2A2 /* discourse.png in Resources */ = {isa = PBXBuildFile; fileRef = FF28C5B7278603750033D2A2 /* discourse.png */; }; + FF28C5BA278604940033D2A2 /* discourse@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = FF28C5B9278604940033D2A2 /* discourse@2x.png */; }; FF2924E51E932D2900FCFA63 /* PINCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2924DF1E932D2900FCFA63 /* PINCache.m */; }; FF2924E61E932D2900FCFA63 /* PINDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2924E21E932D2900FCFA63 /* PINDiskCache.m */; }; FF2924E71E932D2900FCFA63 /* PINMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = FF2924E41E932D2900FCFA63 /* PINMemoryCache.m */; }; @@ -1087,6 +1089,8 @@ FF22FE7516E557D80046165A /* toolbar_tall_background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "toolbar_tall_background@2x.png"; sourceTree = ""; }; FF26125318C00FEC0055FF4D /* AddressBook.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AddressBook.framework; path = System/Library/Frameworks/AddressBook.framework; sourceTree = SDKROOT; }; FF265F10187B6B230080C332 /* fitvid.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = fitvid.js; path = static/fitvid.js; sourceTree = SOURCE_ROOT; }; + FF28C5B7278603750033D2A2 /* discourse.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = discourse.png; sourceTree = ""; }; + FF28C5B9278604940033D2A2 /* discourse@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "discourse@2x.png"; sourceTree = ""; }; FF2924DD1E932D2900FCFA63 /* Nullability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Nullability.h; sourceTree = ""; }; FF2924DE1E932D2900FCFA63 /* PINCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PINCache.h; sourceTree = ""; }; FF2924DF1E932D2900FCFA63 /* PINCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PINCache.m; sourceTree = ""; }; @@ -2246,6 +2250,8 @@ FF5F3A81162B82B5008DBE3E /* rainbow.png */, 43A4C3F315B00A26008787B5 /* arrow.png */, 43A4C3F415B00A26008787B5 /* arrow@2x.png */, + FF28C5B7278603750033D2A2 /* discourse.png */, + FF28C5B9278604940033D2A2 /* discourse@2x.png */, 43A4C3F715B00A26008787B5 /* Background.png */, 43A4C3F815B00A26008787B5 /* Background@2X.png */, 43A4C41115B00A26008787B5 /* fleuron.png */, @@ -3331,6 +3337,7 @@ FFDD847F16E887D3000AA0A2 /* g_icn_folder@2x.png in Resources */, 1740C6881C10FD75005EA453 /* theme_color_dark.png in Resources */, FFDD848016E887D3000AA0A2 /* g_icn_hidden.png in Resources */, + FF28C5B8278603750033D2A2 /* discourse.png in Resources */, FF21B11C1C8228740053938A /* disclosure_border_medium.png in Resources */, 17C67DA02138B2D20027CCAE /* traverse_next_vert@2x.png in Resources */, FFDD848116E887D3000AA0A2 /* g_icn_hidden@2x.png in Resources */, @@ -3397,6 +3404,7 @@ 17F39EB526478319004B46D1 /* image_preview_small_right@2x.png in Resources */, FFCDD8F817F4BCB4000C6483 /* Default.png in Resources */, FF5D4017179A00B900349659 /* traverse_send.png in Resources */, + FF28C5BA278604940033D2A2 /* discourse@2x.png in Resources */, FFCDD8FA17F50C08000C6483 /* drag_icon.png in Resources */, FF5D4018179A00B900349659 /* traverse_send@2x.png in Resources */, FF5D401B179A03E700349659 /* traverse_previous_off.png in Resources */, diff --git a/clients/ios/Resources/discourse.png b/clients/ios/Resources/discourse.png new file mode 100644 index 0000000000000000000000000000000000000000..7e3f6c1c34841b25bd88037d581214716fac9714 GIT binary patch literal 495 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyy~STEL88gA~qMxhWK=EYj1(F~maf zY@n?-bD+SSTE$}>or*8loIB*l5s@+Xo>R|$huk%}tkPRA++VOw?3hW`Y^5fJux(8e z8--Xr`Ixfu=30N;ak|!o@#DefnKy4H-emoETew_d?fd$WL}dGTG(LYWOO`e ze#OVH5(-tzBW=Fk;)(28`QM|d+)eMqt1Hfvjz74$Zh6~|xm`jo+a^23+;u2bJ1ejv zl2N9SO)|#)N`>Op^pu@9p2bwl%`z1?x%YVn$<{M1H<*&cC QPXYzDr>mdKI;Vst0AO9fiU0rr literal 0 HcmV?d00001 diff --git a/clients/ios/Resources/discourse@2x.png b/clients/ios/Resources/discourse@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..43da41683d5581cd8363a30ffc7b38f87bf7e0a6 GIT binary patch literal 899 zcmV-}1AP36P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91B%lKT1ONa40RR91Bme*a04fgS`~Uy~?MXyIR9Fe^S50UWQ4pSao7PBv z6jZbae?UY*PvSv@+CxETm6D%==ta*W)RXieLMa|R_9Ey}5Y#s5k0^q85Ttle3yP?R zB7zjLC}g9yX__5pH+kEn*(7h@LJyL6dGF19GxIU?b|wL6uXYB4WdOa*DQj*6q5~j| zh?m}#S!4miA|#_95wYaT0~~4y(bV7Fu)2DS{q+No@Zt9t6B~t8e2j^a54$?3ONb_a zpMp|poDuOll&S#n1$4#w@B}WYnykk;S)fPecCf6wtkfrCdnW3Eh5U{6LHyjyWhu}o zJKO2UunBgEX7Y!d=$oo4?*tP~QNEP?_KGy%%cKe{=rwh4u6I?*f**II9=v#eLj z9ij+N`M&JRi0m=3$V6U32!24(I>|Wui#1$~=Yeb=^U%>bjRTv%R72_rNhM`-BVfUG zE+q%02Ou_G!(@0~>g7(EKV3kjJB&FaW$HVw@C+Q`>fDsWxiO)PIm1E10HI+_N8Wk` zaYjx7xI_W_7{Yx_Z#iejXiR8wdB0ais)J1vRZBHn+4siL4FW)ke=js=o3QP>L;8Mwh)Tw69W3C6hs|lLL&TC zpHSF%#^1z>db}1$gjxINuQnk(9sTa~kQQ;&)I1#w