Compare commits

..

No commits in common. "ae055f1ffd6b810a029541824c75ee04f51303bc" and "392e51eb3ecb3ac70e2cdb2735c6cd24dd6b018b" have entirely different histories.

9 changed files with 71 additions and 39 deletions

View File

@ -31,8 +31,6 @@
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.social-networking</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>

View File

@ -38,6 +38,7 @@ class Preferences: Codable, ObservableObject {
let container = try decoder.container(keyedBy: CodingKeys.self) let container = try decoder.container(keyedBy: CodingKeys.self)
self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme) self.theme = try container.decode(UIUserInterfaceStyle.self, forKey: .theme)
self.showRepliesInProfiles = try container.decode(Bool.self, forKey: .showRepliesInProfiles)
self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle) self.avatarStyle = try container.decode(AvatarStyle.self, forKey: .avatarStyle)
self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames) self.hideCustomEmojiInUsernames = try container.decode(Bool.self, forKey: .hideCustomEmojiInUsernames)
self.showIsStatusReplyIcon = try container.decode(Bool.self, forKey: .showIsStatusReplyIcon) self.showIsStatusReplyIcon = try container.decode(Bool.self, forKey: .showIsStatusReplyIcon)
@ -67,6 +68,7 @@ class Preferences: Codable, ObservableObject {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(theme, forKey: .theme) try container.encode(theme, forKey: .theme)
try container.encode(showRepliesInProfiles, forKey: .showRepliesInProfiles)
try container.encode(avatarStyle, forKey: .avatarStyle) try container.encode(avatarStyle, forKey: .avatarStyle)
try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames) try container.encode(hideCustomEmojiInUsernames, forKey: .hideCustomEmojiInUsernames)
try container.encode(showIsStatusReplyIcon, forKey: .showIsStatusReplyIcon) try container.encode(showIsStatusReplyIcon, forKey: .showIsStatusReplyIcon)
@ -94,6 +96,7 @@ class Preferences: Codable, ObservableObject {
// MARK: Appearance // MARK: Appearance
@Published var theme = UIUserInterfaceStyle.unspecified @Published var theme = UIUserInterfaceStyle.unspecified
@Published var showRepliesInProfiles = false
@Published var avatarStyle = AvatarStyle.roundRect @Published var avatarStyle = AvatarStyle.roundRect
@Published var hideCustomEmojiInUsernames = false @Published var hideCustomEmojiInUsernames = false
@Published var showIsStatusReplyIcon = false @Published var showIsStatusReplyIcon = false
@ -125,6 +128,7 @@ class Preferences: Codable, ObservableObject {
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
case theme case theme
case showRepliesInProfiles
case avatarStyle case avatarStyle
case hideCustomEmojiInUsernames case hideCustomEmojiInUsernames
case showIsStatusReplyIcon case showIsStatusReplyIcon

View File

@ -30,6 +30,9 @@ struct AppearancePrefsView : View {
Text("Light").tag(UIUserInterfaceStyle.light) Text("Light").tag(UIUserInterfaceStyle.light)
Text("Dark").tag(UIUserInterfaceStyle.dark) Text("Dark").tag(UIUserInterfaceStyle.dark)
} }
Toggle(isOn: $preferences.showRepliesInProfiles) {
Text("Show Replies in Profiles")
}
Toggle(isOn: useCircularAvatars) { Toggle(isOn: useCircularAvatars) {
Text("Use Circular Avatars") Text("Use Circular Avatars")
} }

View File

@ -25,7 +25,7 @@ class ProfileStatusesViewController: EnhancedTableViewController {
private var older: RequestRange? private var older: RequestRange?
private var newer: RequestRange? private var newer: RequestRange?
var loaded = false private var loaded = false
init(accountID: String?, kind: Kind, mastodonController: MastodonController) { init(accountID: String?, kind: Kind, mastodonController: MastodonController) {
self.accountID = accountID self.accountID = accountID
@ -61,14 +61,12 @@ class ProfileStatusesViewController: EnhancedTableViewController {
if !loaded, if !loaded,
let accountID = accountID, let accountID = accountID,
let account = mastodonController.persistentContainer.account(for: accountID) { let account = mastodonController.persistentContainer.account(for: accountID) {
loaded = true
updateUI(account: account) updateUI(account: account)
} }
} }
func updateUI(account: AccountMO) { private func updateUI(account: AccountMO) {
guard !loaded else { return }
loaded = true
if kind == .statuses { if kind == .statuses {
getPinnedStatuses { (response) in getPinnedStatuses { (response) in
guard case let .success(statuses, _) = response else { guard case let .success(statuses, _) = response else {

View File

@ -49,10 +49,6 @@ class ProfileViewController: UIPageViewController {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
deinit {
mastodonController.persistentContainer.account(for: accountID)?.decrementReferenceCount()
}
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
@ -60,6 +56,7 @@ class ProfileViewController: UIPageViewController {
headerView = ProfileHeaderView.create() headerView = ProfileHeaderView.create()
headerView.delegate = self headerView.delegate = self
headerView.updateUI(for: accountID)
selectPage(at: 0, animated: false) selectPage(at: 0, animated: false)
@ -73,24 +70,6 @@ class ProfileViewController: UIPageViewController {
.filter { [weak self] in $0 == self?.accountID } .filter { [weak self] in $0 == self?.accountID }
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [weak self] (_) in self?.updateAccountUI() } .sink { [weak self] (_) in self?.updateAccountUI() }
if mastodonController.persistentContainer.account(for: accountID) != nil {
headerView.updateUI(for: accountID)
} else {
let req = Client.getAccount(id: accountID)
mastodonController.run(req) { [weak self] (response) in
guard let self = self else { return }
guard case let .success(account, _) = response else { fatalError() }
self.mastodonController.persistentContainer.addOrUpdate(account: account, incrementReferenceCount: true) { (account) in
DispatchQueue.main.async {
self.headerView.updateUI(for: self.accountID)
self.pageControllers.forEach {
$0.updateUI(account: account)
}
}
}
}
}
} }
private func updateAccountUI() { private func updateAccountUI() {

View File

@ -185,7 +185,7 @@ extension MenuPreviewProvider {
private func openInSafariAction(url: URL) -> UIAction { private func openInSafariAction(url: URL) -> UIAction {
return createAction(identifier: "openinsafari", title: "Open in Safari", systemImageName: "safari", handler: { (_) in return createAction(identifier: "openinsafari", title: "Open in Safari", systemImageName: "safari", handler: { (_) in
self.navigationDelegate?.selected(url: url, allowUniversalLinks: false) self.navigationDelegate?.selected(url: url)
}) })
} }

View File

@ -10,11 +10,52 @@ import UIKit
import SafariServices import SafariServices
import Pachyderm import Pachyderm
protocol TuskerNavigationDelegate: UIViewController { protocol TuskerNavigationDelegate: class {
var apiController: MastodonController { get } var apiController: MastodonController { get }
func show(_ vc: UIViewController)
func selected(account accountID: String)
func selected(mention: Mention)
func selected(tag: Hashtag)
func selected(url: URL)
func selected(status statusID: String)
func selected(status statusID: String, state: StatusState)
func compose()
func compose(mentioning: String?)
func reply(to statusID: String)
func reply(to statusID: String, mentioningAcct: String?)
func loadingLargeImage(url: URL, cache: ImageCache, description: String?, animatingFrom sourceView: UIImageView) -> LoadingLargeImageViewController
func showLoadingLargeImage(url: URL, cache: ImageCache, description: String?, animatingFrom sourceView: UIImageView)
func gallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int) -> GalleryViewController
func showGallery(attachments: [Attachment], sourceViews: [UIImageView?], startIndex: Int)
func showMoreOptions(forStatus statusID: String, sourceView: UIView?)
func showMoreOptions(forAccount accountID: String, sourceView: UIView?)
func showMoreOptions(forURL url: URL, sourceView: UIView?)
func showFollowedByList(accountIDs: [String])
func statusActionAccountList(action: StatusActionAccountListTableViewController.ActionType, statusID: String, statusState state: StatusState, accountIDs: [String]?) -> StatusActionAccountListTableViewController
} }
extension TuskerNavigationDelegate { extension TuskerNavigationDelegate where Self: UIViewController {
func show(_ vc: UIViewController) { func show(_ vc: UIViewController) {
if vc is LargeImageViewController || vc is GalleryViewController || vc is SFSafariViewController { if vc is LargeImageViewController || vc is GalleryViewController || vc is SFSafariViewController {
@ -42,7 +83,7 @@ extension TuskerNavigationDelegate {
show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self) show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self)
} }
func selected(url: URL, allowUniversalLinks: Bool = true) { func selected(url: URL) {
func openSafari() { func openSafari() {
if Preferences.shared.useInAppSafari { if Preferences.shared.useInAppSafari {
let config = SFSafariViewController.Configuration() let config = SFSafariViewController.Configuration()
@ -53,7 +94,7 @@ extension TuskerNavigationDelegate {
} }
} }
if allowUniversalLinks && Preferences.shared.openLinksInApps { if (Preferences.shared.openLinksInApps) {
UIApplication.shared.open(url, options: [.universalLinksOnly: true]) { (success) in UIApplication.shared.open(url, options: [.universalLinksOnly: true]) { (success) in
if (!success) { if (!success) {
openSafari() openSafari()

View File

@ -46,6 +46,18 @@ class ProfileHeaderView: UIView {
private var accountUpdater: Cancellable? private var accountUpdater: Cancellable?
override var frame: CGRect {
didSet {
print("set header frame for \(self)")
}
}
override var bounds: CGRect {
didSet {
print("set header bounds for \(self)")
}
}
deinit { deinit {
avatarRequest?.cancel() avatarRequest?.cancel()
headerRequest?.cancel() headerRequest?.cancel()
@ -81,7 +93,6 @@ class ProfileHeaderView: UIView {
func updateUI(for accountID: String) { func updateUI(for accountID: String) {
self.accountID = accountID self.accountID = accountID
guard let mastodonController = mastodonController else { return }
guard let account = mastodonController.persistentContainer.account(for: accountID) else { guard let account = mastodonController.persistentContainer.account(for: accountID) else {
fatalError("Missing cached account \(accountID)") fatalError("Missing cached account \(accountID)")
} }

View File

@ -102,8 +102,7 @@ class BaseStatusTableViewCell: UITableViewCell {
.filter { [unowned self] in $0 == self.statusID } .filter { [unowned self] in $0 == self.statusID }
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [unowned self] in .sink { [unowned self] in
if let mastodonController = mastodonController, if let status = self.mastodonController.persistentContainer.status(for: $0) {
let status = mastodonController.persistentContainer.status(for: $0) {
self.updateStatusState(status: status) self.updateStatusState(status: status)
} }
} }
@ -114,8 +113,7 @@ class BaseStatusTableViewCell: UITableViewCell {
.filter { [unowned self] in $0 == self.accountID } .filter { [unowned self] in $0 == self.accountID }
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink { [unowned self] in .sink { [unowned self] in
if let mastodonController = mastodonController, if let account = self.mastodonController.persistentContainer.account(for: $0) {
let account = mastodonController.persistentContainer.account(for: $0) {
self.updateUI(account: account) self.updateUI(account: account)
} }
} }