Compare commits
8 Commits
392e51eb3e
...
ae055f1ffd
Author | SHA1 | Date |
---|---|---|
Shadowfacts | ae055f1ffd | |
Shadowfacts | eef9b96a1a | |
Shadowfacts | 29aed65b99 | |
Shadowfacts | 090746f292 | |
Shadowfacts | af300a3559 | |
Shadowfacts | 79eb23ef5d | |
Shadowfacts | 60565f9625 | |
Shadowfacts | 70bedf17a8 |
|
@ -31,6 +31,8 @@
|
||||||
</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>
|
||||||
|
|
|
@ -38,7 +38,6 @@ 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)
|
||||||
|
@ -68,7 +67,6 @@ 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)
|
||||||
|
@ -96,7 +94,6 @@ 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
|
||||||
|
@ -128,7 +125,6 @@ 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
|
||||||
|
|
|
@ -30,9 +30,6 @@ 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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ class ProfileStatusesViewController: EnhancedTableViewController {
|
||||||
private var older: RequestRange?
|
private var older: RequestRange?
|
||||||
private var newer: RequestRange?
|
private var newer: RequestRange?
|
||||||
|
|
||||||
private var loaded = false
|
var loaded = false
|
||||||
|
|
||||||
init(accountID: String?, kind: Kind, mastodonController: MastodonController) {
|
init(accountID: String?, kind: Kind, mastodonController: MastodonController) {
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
@ -61,12 +61,14 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateUI(account: AccountMO) {
|
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 {
|
||||||
|
|
|
@ -49,6 +49,10 @@ 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()
|
||||||
|
|
||||||
|
@ -56,7 +60,6 @@ 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)
|
||||||
|
|
||||||
|
@ -70,6 +73,24 @@ 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() {
|
||||||
|
|
|
@ -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)
|
self.navigationDelegate?.selected(url: url, allowUniversalLinks: false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,52 +10,11 @@ import UIKit
|
||||||
import SafariServices
|
import SafariServices
|
||||||
import Pachyderm
|
import Pachyderm
|
||||||
|
|
||||||
protocol TuskerNavigationDelegate: class {
|
protocol TuskerNavigationDelegate: UIViewController {
|
||||||
|
|
||||||
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 where Self: UIViewController {
|
extension TuskerNavigationDelegate {
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -83,7 +42,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self)
|
show(HashtagTimelineViewController(for: tag, mastodonController: apiController), sender: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func selected(url: URL) {
|
func selected(url: URL, allowUniversalLinks: Bool = true) {
|
||||||
func openSafari() {
|
func openSafari() {
|
||||||
if Preferences.shared.useInAppSafari {
|
if Preferences.shared.useInAppSafari {
|
||||||
let config = SFSafariViewController.Configuration()
|
let config = SFSafariViewController.Configuration()
|
||||||
|
@ -94,7 +53,7 @@ extension TuskerNavigationDelegate where Self: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Preferences.shared.openLinksInApps) {
|
if allowUniversalLinks && 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()
|
||||||
|
|
|
@ -46,18 +46,6 @@ 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()
|
||||||
|
@ -93,6 +81,7 @@ 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)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,8 @@ 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 status = self.mastodonController.persistentContainer.status(for: $0) {
|
if let mastodonController = mastodonController,
|
||||||
|
let status = mastodonController.persistentContainer.status(for: $0) {
|
||||||
self.updateStatusState(status: status)
|
self.updateStatusState(status: status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,8 @@ 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 account = self.mastodonController.persistentContainer.account(for: $0) {
|
if let mastodonController = mastodonController,
|
||||||
|
let account = mastodonController.persistentContainer.account(for: $0) {
|
||||||
self.updateUI(account: account)
|
self.updateUI(account: account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue