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