Compare commits
No commits in common. "f7127b84d81efaab5057d6cbab19b3c435546196" and "e18a09f4ac5f27a5fcc4fddf226312d763eb8729" have entirely different histories.
f7127b84d8
...
e18a09f4ac
|
@ -65,15 +65,15 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
private func upsert(status: Status, incrementReferenceCount: Bool, context: NSManagedObjectContext) -> StatusMO {
|
private func upsert(status: Status, incrementReferenceCount: Bool) -> StatusMO {
|
||||||
if let statusMO = self.status(for: status.id, in: context) {
|
if let statusMO = self.status(for: status.id, in: self.backgroundContext) {
|
||||||
statusMO.updateFrom(apiStatus: status, container: self)
|
statusMO.updateFrom(apiStatus: status, container: self)
|
||||||
if incrementReferenceCount {
|
if incrementReferenceCount {
|
||||||
statusMO.incrementReferenceCount()
|
statusMO.incrementReferenceCount()
|
||||||
}
|
}
|
||||||
return statusMO
|
return statusMO
|
||||||
} else {
|
} else {
|
||||||
let statusMO = StatusMO(apiStatus: status, container: self, context: context)
|
let statusMO = StatusMO(apiStatus: status, container: self, context: self.backgroundContext)
|
||||||
if incrementReferenceCount {
|
if incrementReferenceCount {
|
||||||
statusMO.incrementReferenceCount()
|
statusMO.incrementReferenceCount()
|
||||||
}
|
}
|
||||||
|
@ -81,12 +81,11 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addOrUpdate(status: Status, incrementReferenceCount: Bool, context: NSManagedObjectContext? = nil, completion: ((StatusMO) -> Void)? = nil) {
|
func addOrUpdate(status: Status, incrementReferenceCount: Bool, completion: ((StatusMO) -> Void)? = nil) {
|
||||||
let context = context ?? backgroundContext
|
backgroundContext.perform {
|
||||||
context.perform {
|
let statusMO = self.upsert(status: status, incrementReferenceCount: incrementReferenceCount)
|
||||||
let statusMO = self.upsert(status: status, incrementReferenceCount: incrementReferenceCount, context: context)
|
if self.backgroundContext.hasChanges {
|
||||||
if context.hasChanges {
|
try! self.backgroundContext.save()
|
||||||
try! context.save()
|
|
||||||
}
|
}
|
||||||
completion?(statusMO)
|
completion?(statusMO)
|
||||||
self.statusSubject.send(status.id)
|
self.statusSubject.send(status.id)
|
||||||
|
@ -95,7 +94,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
|
|
||||||
func addAll(statuses: [Status], completion: (() -> Void)? = nil) {
|
func addAll(statuses: [Status], completion: (() -> Void)? = nil) {
|
||||||
backgroundContext.perform {
|
backgroundContext.perform {
|
||||||
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true, context: self.backgroundContext) }
|
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true) }
|
||||||
if self.backgroundContext.hasChanges {
|
if self.backgroundContext.hasChanges {
|
||||||
try! self.backgroundContext.save()
|
try! self.backgroundContext.save()
|
||||||
}
|
}
|
||||||
|
@ -195,7 +194,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
// filter out mentions, otherwise we would double increment the reference count of those accounts
|
// filter out mentions, otherwise we would double increment the reference count of those accounts
|
||||||
// since the status has the same account as the notification
|
// since the status has the same account as the notification
|
||||||
let accounts = notifications.filter { $0.kind != .mention }.map { $0.account }
|
let accounts = notifications.filter { $0.kind != .mention }.map { $0.account }
|
||||||
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true, context: self.backgroundContext) }
|
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true) }
|
||||||
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
||||||
if self.backgroundContext.hasChanges {
|
if self.backgroundContext.hasChanges {
|
||||||
try! self.backgroundContext.save()
|
try! self.backgroundContext.save()
|
||||||
|
@ -215,7 +214,7 @@ class MastodonCachePersistentStore: NSPersistentContainer {
|
||||||
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
accounts.forEach { self.upsert(account: $0, incrementReferenceCount: true) }
|
||||||
updatedAccounts.append(contentsOf: accounts.map { $0.id })
|
updatedAccounts.append(contentsOf: accounts.map { $0.id })
|
||||||
}, { (statuses) in
|
}, { (statuses) in
|
||||||
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true, context: self.backgroundContext) }
|
statuses.forEach { self.upsert(status: $0, incrementReferenceCount: true) }
|
||||||
updatedStatuses.append(contentsOf: statuses.map { $0.id })
|
updatedStatuses.append(contentsOf: statuses.map { $0.id })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ extension MenuPreviewProvider {
|
||||||
|
|
||||||
if mastodonController.account != nil && mastodonController.account.id == status.account.id {
|
if mastodonController.account != nil && mastodonController.account.id == status.account.id {
|
||||||
let pinned = status.pinned ?? false
|
let pinned = status.pinned ?? false
|
||||||
actionsSection.append(createAction(identifier: "pin", title: pinned ? "Unpin" : "Pin", systemImageName: pinned ? "pin.slash" : "pin", handler: { [weak self] (_) in
|
actionsSection.append(createAction(identifier: "", title: pinned ? "Unpin" : "Pin", systemImageName: pinned ? "pin.slash" : "pin", handler: { [weak self] (_) in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let request = (pinned ? Status.unpin : Status.pin)(status.id)
|
let request = (pinned ? Status.unpin : Status.pin)(status.id)
|
||||||
self.mastodonController?.run(request, completion: { [weak self] (response) in
|
self.mastodonController?.run(request, completion: { [weak self] (response) in
|
||||||
|
@ -188,20 +188,6 @@ extension MenuPreviewProvider {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
if status.poll != nil {
|
|
||||||
actionsSection.insert(createAction(identifier: "refresh", title: "Refresh Poll", systemImageName: "arrow.clockwise", handler: { [weak self] (_) in
|
|
||||||
guard let mastodonController = self?.mastodonController else { return }
|
|
||||||
let request = Client.getStatus(id: status.id)
|
|
||||||
mastodonController.run(request, completion: { (response) in
|
|
||||||
if case let .success(status, _) = response {
|
|
||||||
// todo: this shouldn't really use the viewContext, but for some reason saving the
|
|
||||||
// backgroundContext with the new version of the status isn't updating the viewContext
|
|
||||||
mastodonController.persistentContainer.addOrUpdate(status: status, incrementReferenceCount: false, context: mastodonController.persistentContainer.viewContext)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}), at: 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
var shareSection = [
|
var shareSection = [
|
||||||
openInSafariAction(url: status.url!),
|
openInSafariAction(url: status.url!),
|
||||||
createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
createAction(identifier: "share", title: "Share...", systemImageName: "square.and.arrow.up", handler: { [weak self, weak sourceView] (_) in
|
||||||
|
|
|
@ -34,19 +34,8 @@ class PollOptionView: UIView {
|
||||||
label.setEmojis(poll.emojis, identifier: poll.id)
|
label.setEmojis(poll.emojis, identifier: poll.id)
|
||||||
addSubview(label)
|
addSubview(label)
|
||||||
|
|
||||||
let percentLabel = UILabel()
|
|
||||||
percentLabel.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
percentLabel.text = "100%"
|
|
||||||
percentLabel.isHidden = true
|
|
||||||
addSubview(percentLabel)
|
|
||||||
|
|
||||||
if (poll.voted ?? false) || poll.effectiveExpired,
|
if (poll.voted ?? false) || poll.effectiveExpired,
|
||||||
let optionVotes = option.votesCount {
|
let optionVotes = option.votesCount {
|
||||||
let frac = poll.votesCount == 0 ? 0 : CGFloat(optionVotes) / CGFloat(poll.votesCount)
|
|
||||||
|
|
||||||
percentLabel.isHidden = false
|
|
||||||
percentLabel.text = String(format: "%.0f%%", frac * 100)
|
|
||||||
|
|
||||||
let fillView = UIView()
|
let fillView = UIView()
|
||||||
fillView.translatesAutoresizingMaskIntoConstraints = false
|
fillView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
fillView.backgroundColor = tintColor.withAlphaComponent(0.6)
|
fillView.backgroundColor = tintColor.withAlphaComponent(0.6)
|
||||||
|
@ -56,7 +45,7 @@ class PollOptionView: UIView {
|
||||||
|
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
fillView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
fillView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
fillView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: frac),
|
fillView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: poll.votesCount == 0 ? 0 : CGFloat(optionVotes) / CGFloat(poll.votesCount)),
|
||||||
fillView.topAnchor.constraint(equalTo: topAnchor),
|
fillView.topAnchor.constraint(equalTo: topAnchor),
|
||||||
fillView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
fillView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
])
|
])
|
||||||
|
@ -76,11 +65,7 @@ class PollOptionView: UIView {
|
||||||
label.topAnchor.constraint(equalTo: topAnchor),
|
label.topAnchor.constraint(equalTo: topAnchor),
|
||||||
label.bottomAnchor.constraint(equalTo: bottomAnchor),
|
label.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||||
label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: 8),
|
label.leadingAnchor.constraint(equalTo: checkbox.trailingAnchor, constant: 8),
|
||||||
label.trailingAnchor.constraint(equalTo: percentLabel.leadingAnchor),
|
label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
|
||||||
|
|
||||||
percentLabel.topAnchor.constraint(equalTo: topAnchor),
|
|
||||||
percentLabel.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
||||||
percentLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,6 @@ class PollOptionsView: UIControl {
|
||||||
private let animationDuration: TimeInterval = 0.1
|
private let animationDuration: TimeInterval = 0.1
|
||||||
private let scaledTransform = CGAffineTransform(scaleX: 0.95, y: 0.95)
|
private let scaledTransform = CGAffineTransform(scaleX: 0.95, y: 0.95)
|
||||||
|
|
||||||
private let generator = UIImpactFeedbackGenerator(style: .soft)
|
|
||||||
|
|
||||||
override var isEnabled: Bool {
|
override var isEnabled: Bool {
|
||||||
didSet {
|
didSet {
|
||||||
options.forEach { $0.checkbox.readOnly = !isEnabled }
|
options.forEach { $0.checkbox.readOnly = !isEnabled }
|
||||||
|
@ -108,9 +106,6 @@ class PollOptionsView: UIControl {
|
||||||
}
|
}
|
||||||
animator.startAnimation()
|
animator.startAnimation()
|
||||||
|
|
||||||
generator.impactOccurred()
|
|
||||||
generator.prepare()
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,11 +130,6 @@ class PollOptionsView: UIControl {
|
||||||
view.transform = index == newIndex ? self.scaledTransform : .identity
|
view.transform = index == newIndex ? self.scaledTransform : .identity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if newIndex != nil {
|
|
||||||
generator.impactOccurred()
|
|
||||||
generator.prepare()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -136,8 +136,6 @@ class StatusPollView: UIView {
|
||||||
voteButton.isEnabled = false
|
voteButton.isEnabled = false
|
||||||
voteButton.setTitle("Voted", for: .disabled)
|
voteButton.setTitle("Voted", for: .disabled)
|
||||||
|
|
||||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
|
||||||
|
|
||||||
let request = Poll.vote(poll.id, choices: optionsView.checkedOptionIndices)
|
let request = Poll.vote(poll.id, choices: optionsView.checkedOptionIndices)
|
||||||
mastodonController.run(request) { (response) in
|
mastodonController.run(request) { (response) in
|
||||||
switch response {
|
switch response {
|
||||||
|
|
Loading…
Reference in New Issue