From 0fd6957cdba6a62c947d300625e3297f6ea0bb0a Mon Sep 17 00:00:00 2001 From: kean Date: Fri, 20 Dec 2024 15:46:09 -0500 Subject: [PATCH] Add missing social sharing icons --- .../Classes/Models/PublicizeService.swift | 1 + .../Blog/Sharing/PublicizeServiceCell.swift | 90 ++++++++++++++++++ .../Blog/Sharing/SharingViewController.m | 74 +++++--------- .../JetpackSocialNoConnectionView.swift | 2 +- ...04761532104096_2740029438399114184_n-2.png | Bin 0 -> 7689 bytes .../icon-threads.imageset/Contents.json | 12 +++ 6 files changed, 127 insertions(+), 52 deletions(-) create mode 100644 WordPress/Classes/ViewRelated/Blog/Sharing/PublicizeServiceCell.swift create mode 100644 WordPress/Jetpack/AppImages.xcassets/Social/icon-threads.imageset/361591942_304761532104096_2740029438399114184_n-2.png create mode 100644 WordPress/Jetpack/AppImages.xcassets/Social/icon-threads.imageset/Contents.json diff --git a/WordPress/Classes/Models/PublicizeService.swift b/WordPress/Classes/Models/PublicizeService.swift index e056aec957f6..d4842e0506a2 100644 --- a/WordPress/Classes/Models/PublicizeService.swift +++ b/WordPress/Classes/Models/PublicizeService.swift @@ -37,6 +37,7 @@ extension PublicizeService { case linkedin case instagram = "instagram-business" case mastodon + case threads case unknown /// Returns the local image for the icon representing the social network. diff --git a/WordPress/Classes/ViewRelated/Blog/Sharing/PublicizeServiceCell.swift b/WordPress/Classes/ViewRelated/Blog/Sharing/PublicizeServiceCell.swift new file mode 100644 index 000000000000..ebeaa18c8c4b --- /dev/null +++ b/WordPress/Classes/ViewRelated/Blog/Sharing/PublicizeServiceCell.swift @@ -0,0 +1,90 @@ +import UIKit +import WordPressUI + +final class PublicizeServiceCell: UITableViewCell { + let iconView = AsyncImageView() + let titleLabel = UILabel() + let detailsLabel = UILabel() + + @objc class var cellId: String { "PublicizeServiceCell" } + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + detailsLabel.font = .preferredFont(forTextStyle: .footnote) + detailsLabel.textColor = .secondaryLabel + + let stackView = UIStackView(alignment: .center, spacing: 12, [ + iconView, + UIStackView(axis: .vertical, alignment: .leading, spacing: 2, [titleLabel, detailsLabel]) + ]) + contentView.addSubview(stackView) + stackView.pinEdges(to: contentView.layoutMarginsGuide) + + NSLayoutConstraint.activate([ + iconView.widthAnchor.constraint(equalToConstant: 28), + iconView.heightAnchor.constraint(equalToConstant: 28), + ]) + iconView.layer.cornerRadius = 8 + iconView.layer.masksToBounds = true + iconView.backgroundColor = UIColor.white + + iconView.contentMode = .scaleAspectFit + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func prepareForReuse() { + super.prepareForReuse() + + accessoryView = .none + iconView.prepareForReuse() + } + + @objc func configure(with service: PublicizeService, connections: [PublicizeConnection]) { + let name = service.name + if name != .unknown && !name.hasModernRemoteLogo { + iconView.image = name.localIconImage + } else if let imageURL = URL(string: service.icon) { + iconView.setImage(with: imageURL) + } else { + iconView.image = UIImage(named: "social-default") + } + + titleLabel.text = service.label + + detailsLabel.isHidden = connections.isEmpty + if connections.count > 2 { + detailsLabel.text = String(format: Strings.numberOfAccounts, connections.count) + } else { + detailsLabel.text = connections + .map(\.externalDisplay) + .joined(separator: ", ") + } + + if service.isSupported { + if connections.contains(where: { $0.requiresUserAction() }) { + accessoryView = WPStyleGuide.sharingCellWarningAccessoryImageView() + } + } else { + accessoryView = WPStyleGuide.sharingCellErrorAccessoryImageView() + } + } +} + +private extension PublicizeService.ServiceName { + /// We no longer need to provide local overrides for these on this screen + /// as the remote images are good. + var hasModernRemoteLogo: Bool { + [ + PublicizeService.ServiceName.instagram, + PublicizeService.ServiceName.mastodon + ].contains(self) + } +} + +private enum Strings { + static let numberOfAccounts = NSLocalizedString("socialSharing.connectionDetails.nAccount", value: "%d accounts", comment: "The number of connected accounts on a third party sharing service connected to the user's blog. The '%d' is a placeholder for the number of accounts.") +} diff --git a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingViewController.m b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingViewController.m index 077c4846c677..0ddf6bc3eda4 100644 --- a/WordPress/Classes/ViewRelated/Blog/Sharing/SharingViewController.m +++ b/WordPress/Classes/ViewRelated/Blog/Sharing/SharingViewController.m @@ -66,6 +66,7 @@ - (void)viewDidLoad action:@selector(doneButtonTapped)]; } + [self.tableView registerClass:[PublicizeServiceCell class] forCellReuseIdentifier:PublicizeServiceCell.cellId]; self.tableView.cellLayoutMarginsFollowReadableWidth = YES; [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; [self.publicizeServicesState addInitialConnections:[self allConnections]]; @@ -237,32 +238,16 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - WPTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (!cell) { - cell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; - } - - [WPStyleGuide configureTableViewCell:cell]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - SharingSectionType sectionType = [self sectionTypeForIndex:indexPath.section]; switch (sectionType) { case SharingSectionAvailableServices: // fallthrough case SharingSectionUnsupported: - [self configurePublicizeCell:cell atIndexPath:indexPath]; - break; - + return [self makePublicizeCellAtIndexPath:indexPath]; case SharingSectionSharingButtons: - cell.textLabel.text = NSLocalizedString(@"Manage", @"Verb. Text label. Tapping displays a screen where the user can configure 'share' buttons for third-party services."); - cell.detailTextLabel.text = nil; - cell.imageView.image = nil; - break; - + return [self makeManageButtonCell]; default: return [UITableViewCell new]; } - - return cell; } - (PublicizeService *)publicizeServiceForIndexPath:(NSIndexPath *)indexPath @@ -278,51 +263,38 @@ - (PublicizeService *)publicizeServiceForIndexPath:(NSIndexPath *)indexPath } } -- (void)configurePublicizeCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath +- (UITableViewCell *)makePublicizeCellAtIndexPath:(NSIndexPath *)indexPath { + PublicizeServiceCell *cell = [self.tableView dequeueReusableCellWithIdentifier:PublicizeServiceCell.cellId]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + PublicizeService *publicizer = [self publicizeServiceForIndexPath:indexPath]; NSArray *connections = [self connectionsForService:publicizer]; // TODO: Remove? if ([publicizer.serviceID isEqualToString:PublicizeService.googlePlusServiceID] && [connections count] == 0) { // Temporarily hiding Google+ cell.hidden = YES; - return; - } - - // Configure the image - UIImage *image = [WPStyleGuide socialIconFor:publicizer.serviceID]; - [cell.imageView setImage:image]; - - // Configure the text - cell.textLabel.text = publicizer.label; - - // Show the name(s) or number of connections. - NSString *str = @""; - if ([connections count] > 2) { - NSString *format = NSLocalizedString(@"%d accounts", @"The number of connected accounts on a third party sharing service connected to the user's blog. The '%d' is a placeholder for the number of accounts."); - str = [NSString stringWithFormat:format, [connections count]]; - } else { - NSMutableArray *names = [NSMutableArray array]; - for (PublicizeConnection *pubConn in connections) { - [names addObject:pubConn.externalDisplay]; - } - str = [names componentsJoinedByString:@", "]; + return cell; } - cell.detailTextLabel.text = str; + [cell configureWith:publicizer connections:connections]; + return cell; +} - if (![publicizer isSupported]) { - cell.accessoryView = [WPStyleGuide sharingCellErrorAccessoryImageView]; - return; +- (UITableViewCell *)makeManageButtonCell +{ + WPTableViewCell *cell = [self. + tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (!cell) { + cell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier]; } - // Check if any of the connections are broken. - for (PublicizeConnection *pubConn in connections) { - if ([pubConn requiresUserAction]) { - cell.accessoryView = [WPStyleGuide sharingCellWarningAccessoryImageView]; - break; - } - } + [WPStyleGuide configureTableViewCell:cell]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.textLabel.text = NSLocalizedString(@"Manage", @"Verb. Text label. Tapping displays a screen where the user can configure 'share' buttons for third-party services."); + cell.detailTextLabel.text = nil; + cell.imageView.image = nil; + return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift b/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift index f1d7556e0c5a..a958a0469153 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift @@ -40,7 +40,7 @@ struct JetpackSocialNoConnectionView: View { } func iconImage(image: UIImage, url: URL?) -> some View { - AsyncImage(url: url) { image in + CachedAsyncImage(url: url) { image in image .icon(backgroundColor: viewModel.preferredBackgroundColor) } placeholder: { diff --git a/WordPress/Jetpack/AppImages.xcassets/Social/icon-threads.imageset/361591942_304761532104096_2740029438399114184_n-2.png b/WordPress/Jetpack/AppImages.xcassets/Social/icon-threads.imageset/361591942_304761532104096_2740029438399114184_n-2.png new file mode 100644 index 0000000000000000000000000000000000000000..e75640c24a0248163fd3c590ecfdd594c74c7071 GIT binary patch literal 7689 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