Compare commits
No commits in common. "ac0dedfd3d6c6b6414be35204d7246b4e6f9ecc9" and "abe2bbdfd43327b2d67ba782eff913e1e9262dc2" have entirely different histories.
ac0dedfd3d
...
abe2bbdfd4
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,18 +1,5 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
## 2023.1 (61)
|
|
||||||
Features/Improvements:
|
|
||||||
- Add report UI
|
|
||||||
- Add accent color preference
|
|
||||||
- Start playing videos immediately when gallery opens
|
|
||||||
|
|
||||||
Bugfixes:
|
|
||||||
- Fix crash when trying to load deleted status for state restoration/sync
|
|
||||||
- Fix crash when trying to restore state for non-pinned timeline
|
|
||||||
- Fix crash due to relationships being cached longer than their corresponding accounts
|
|
||||||
- Fix crash if preferences change when there are cells that haven't yet been displayed
|
|
||||||
- Fix crash when displaying poll finished notifications
|
|
||||||
|
|
||||||
## 2023.1 (60)
|
## 2023.1 (60)
|
||||||
Features/Improvements:
|
Features/Improvements:
|
||||||
- Allow sharing gifv attachments
|
- Allow sharing gifv attachments
|
||||||
|
|
|
@ -323,20 +323,11 @@ public class Client {
|
||||||
return Request<[Report]>(method: .get, path: "/api/v1/reports")
|
return Request<[Report]>(method: .get, path: "/api/v1/reports")
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func report(
|
public static func report(account: Account, statuses: [Status], comment: String) -> Request<Report> {
|
||||||
account: String,
|
|
||||||
statuses: [String],
|
|
||||||
comment: String,
|
|
||||||
forward: Bool,
|
|
||||||
category: String,
|
|
||||||
ruleIDs: [String]
|
|
||||||
) -> Request<Report> {
|
|
||||||
return Request<Report>(method: .post, path: "/api/v1/reports", body: ParametersBody([
|
return Request<Report>(method: .post, path: "/api/v1/reports", body: ParametersBody([
|
||||||
"account_id" => account,
|
"account_id" => account.id,
|
||||||
"comment" => comment,
|
"comment" => comment
|
||||||
"forward" => forward,
|
] + "status_ids" => statuses.map { $0.id }))
|
||||||
"category" => category,
|
|
||||||
] + "status_ids" => statuses + "rule_ids" => ruleIDs))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Search
|
// MARK: - Search
|
||||||
|
|
|
@ -94,12 +94,11 @@ public final class Account: AccountProtocol, Decodable {
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func getStatuses(_ accountID: String, range: RequestRange = .default, onlyMedia: Bool? = nil, pinned: Bool? = nil, excludeReplies: Bool? = nil, excludeReblogs: Bool? = nil) -> Request<[Status]> {
|
public static func getStatuses(_ accountID: String, range: RequestRange = .default, onlyMedia: Bool? = nil, pinned: Bool? = nil, excludeReplies: Bool? = nil) -> Request<[Status]> {
|
||||||
var request = Request<[Status]>(method: .get, path: "/api/v1/accounts/\(accountID)/statuses", queryParameters: [
|
var request = Request<[Status]>(method: .get, path: "/api/v1/accounts/\(accountID)/statuses", queryParameters: [
|
||||||
"only_media" => onlyMedia,
|
"only_media" => onlyMedia,
|
||||||
"pinned" => pinned,
|
"pinned" => pinned,
|
||||||
"exclude_replies" => excludeReplies,
|
"exclude_replies" => excludeReplies
|
||||||
"exclude_reblogs" => excludeReblogs,
|
|
||||||
])
|
])
|
||||||
request.range = range
|
request.range = range
|
||||||
return request
|
return request
|
||||||
|
|
|
@ -20,7 +20,6 @@ public class Instance: Decodable {
|
||||||
public let languages: [String]?
|
public let languages: [String]?
|
||||||
public let stats: Stats?
|
public let stats: Stats?
|
||||||
public let configuration: Configuration?
|
public let configuration: Configuration?
|
||||||
public let rules: [Rule]?
|
|
||||||
|
|
||||||
// pleroma doesn't currently implement these
|
// pleroma doesn't currently implement these
|
||||||
public let contactAccount: Account?
|
public let contactAccount: Account?
|
||||||
|
@ -58,7 +57,6 @@ public class Instance: Decodable {
|
||||||
self.thumbnail = try? container.decodeIfPresent(URL.self, forKey: .thumbnail)
|
self.thumbnail = try? container.decodeIfPresent(URL.self, forKey: .thumbnail)
|
||||||
|
|
||||||
self.configuration = try? container.decodeIfPresent(Configuration.self, forKey: .configuration)
|
self.configuration = try? container.decodeIfPresent(Configuration.self, forKey: .configuration)
|
||||||
self.rules = try? container.decodeIfPresent([Rule].self, forKey: .rules)
|
|
||||||
|
|
||||||
if let maxTootCharacters = try? container.decodeIfPresent(Int.self, forKey: .maxTootCharacters) {
|
if let maxTootCharacters = try? container.decodeIfPresent(Int.self, forKey: .maxTootCharacters) {
|
||||||
self.maxTootCharacters = maxTootCharacters
|
self.maxTootCharacters = maxTootCharacters
|
||||||
|
@ -85,7 +83,6 @@ public class Instance: Decodable {
|
||||||
case stats
|
case stats
|
||||||
case configuration
|
case configuration
|
||||||
case contactAccount = "contact_account"
|
case contactAccount = "contact_account"
|
||||||
case rules
|
|
||||||
|
|
||||||
case maxTootCharacters = "max_toot_chars"
|
case maxTootCharacters = "max_toot_chars"
|
||||||
case pollLimits = "poll_limits"
|
case pollLimits = "poll_limits"
|
||||||
|
@ -170,10 +167,3 @@ extension Instance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Instance {
|
|
||||||
public struct Rule: Decodable, Identifiable {
|
|
||||||
public let id: String
|
|
||||||
public let text: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -145,11 +145,6 @@
|
||||||
D6552367289870790048A653 /* ScreenCorners in Frameworks */ = {isa = PBXBuildFile; productRef = D6552366289870790048A653 /* ScreenCorners */; };
|
D6552367289870790048A653 /* ScreenCorners in Frameworks */ = {isa = PBXBuildFile; productRef = D6552366289870790048A653 /* ScreenCorners */; };
|
||||||
D659F35E2953A212002D944A /* TTTKit in Frameworks */ = {isa = PBXBuildFile; productRef = D659F35D2953A212002D944A /* TTTKit */; };
|
D659F35E2953A212002D944A /* TTTKit in Frameworks */ = {isa = PBXBuildFile; productRef = D659F35D2953A212002D944A /* TTTKit */; };
|
||||||
D659F36229541065002D944A /* TTTView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D659F36129541065002D944A /* TTTView.swift */; };
|
D659F36229541065002D944A /* TTTView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D659F36129541065002D944A /* TTTView.swift */; };
|
||||||
D65B4B542971F71D00DABDFB /* EditedReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B532971F71D00DABDFB /* EditedReport.swift */; };
|
|
||||||
D65B4B562971F98300DABDFB /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B552971F98300DABDFB /* ReportView.swift */; };
|
|
||||||
D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */; };
|
|
||||||
D65B4B5A29720AB000DABDFB /* ReportStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B5929720AB000DABDFB /* ReportStatusView.swift */; };
|
|
||||||
D65B4B5E2973040D00DABDFB /* ReportAddStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */; };
|
|
||||||
D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */; };
|
D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */; };
|
||||||
D65F613423AEAB6600F3CFD3 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65F613323AEAB6600F3CFD3 /* OnboardingTests.swift */; };
|
D65F613423AEAB6600F3CFD3 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65F613323AEAB6600F3CFD3 /* OnboardingTests.swift */; };
|
||||||
D6620ACE2511A0ED00312CA0 /* StatusStateResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6620ACD2511A0ED00312CA0 /* StatusStateResolver.swift */; };
|
D6620ACE2511A0ED00312CA0 /* StatusStateResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6620ACD2511A0ED00312CA0 /* StatusStateResolver.swift */; };
|
||||||
|
@ -532,11 +527,6 @@
|
||||||
D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSwipeActionProvider.swift; sourceTree = "<group>"; };
|
D6538944214D6D7500E3CEFC /* TableViewSwipeActionProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSwipeActionProvider.swift; sourceTree = "<group>"; };
|
||||||
D653F410267D1E32004E32B1 /* DiffableTimelineLikeTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableTimelineLikeTableViewController.swift; sourceTree = "<group>"; };
|
D653F410267D1E32004E32B1 /* DiffableTimelineLikeTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiffableTimelineLikeTableViewController.swift; sourceTree = "<group>"; };
|
||||||
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = "<group>"; };
|
D659F36129541065002D944A /* TTTView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TTTView.swift; sourceTree = "<group>"; };
|
||||||
D65B4B532971F71D00DABDFB /* EditedReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditedReport.swift; sourceTree = "<group>"; };
|
|
||||||
D65B4B552971F98300DABDFB /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = "<group>"; };
|
|
||||||
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportSelectRulesView.swift; sourceTree = "<group>"; };
|
|
||||||
D65B4B5929720AB000DABDFB /* ReportStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportStatusView.swift; sourceTree = "<group>"; };
|
|
||||||
D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportAddStatusView.swift; sourceTree = "<group>"; };
|
|
||||||
D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundableViewController.swift; sourceTree = "<group>"; };
|
D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackgroundableViewController.swift; sourceTree = "<group>"; };
|
||||||
D65F612D23AE990C00F3CFD3 /* Embassy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Embassy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
D65F612D23AE990C00F3CFD3 /* Embassy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Embassy.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D65F613023AE99E000F3CFD3 /* Ambassador.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Ambassador.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
D65F613023AE99E000F3CFD3 /* Ambassador.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Ambassador.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -820,7 +810,6 @@
|
||||||
D677284D24ECC01D00C732D3 /* Draft.swift */,
|
D677284D24ECC01D00C732D3 /* Draft.swift */,
|
||||||
D627FF75217E923E00CC0648 /* DraftsManager.swift */,
|
D627FF75217E923E00CC0648 /* DraftsManager.swift */,
|
||||||
D61F75AE293AF50C00C0B37F /* EditedFilter.swift */,
|
D61F75AE293AF50C00C0B37F /* EditedFilter.swift */,
|
||||||
D65B4B532971F71D00DABDFB /* EditedReport.swift */,
|
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -974,7 +963,6 @@
|
||||||
D641C783213DD7FE004B4513 /* Onboarding */,
|
D641C783213DD7FE004B4513 /* Onboarding */,
|
||||||
D641C789213DD87E004B4513 /* Preferences */,
|
D641C789213DD87E004B4513 /* Preferences */,
|
||||||
D641C784213DD819004B4513 /* Profile */,
|
D641C784213DD819004B4513 /* Profile */,
|
||||||
D65B4B522971F6E300DABDFB /* Report */,
|
|
||||||
D6BC9DD8232D8BCA002CA326 /* Search */,
|
D6BC9DD8232D8BCA002CA326 /* Search */,
|
||||||
D6A3BC8C2321FF9B00FD64D5 /* Status Action Account List */,
|
D6A3BC8C2321FF9B00FD64D5 /* Status Action Account List */,
|
||||||
D641C781213DD7DD004B4513 /* Timeline */,
|
D641C781213DD7DD004B4513 /* Timeline */,
|
||||||
|
@ -1185,17 +1173,6 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
D65B4B522971F6E300DABDFB /* Report */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
D65B4B552971F98300DABDFB /* ReportView.swift */,
|
|
||||||
D65B4B57297203A700DABDFB /* ReportSelectRulesView.swift */,
|
|
||||||
D65B4B5929720AB000DABDFB /* ReportStatusView.swift */,
|
|
||||||
D65B4B5D2973040D00DABDFB /* ReportAddStatusView.swift */,
|
|
||||||
);
|
|
||||||
path = Report;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
D663626021360A9600C9CBA2 /* Preferences */ = {
|
D663626021360A9600C9CBA2 /* Preferences */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1998,7 +1975,6 @@
|
||||||
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */,
|
D64AAE9726C88DC400FC57FB /* ToastConfiguration.swift in Sources */,
|
||||||
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
|
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */,
|
||||||
D6E9CDA8281A427800BBC98E /* PostService.swift in Sources */,
|
D6E9CDA8281A427800BBC98E /* PostService.swift in Sources */,
|
||||||
D65B4B5E2973040D00DABDFB /* ReportAddStatusView.swift in Sources */,
|
|
||||||
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
|
D6B053A223BD2C0600A066FA /* AssetPickerViewController.swift in Sources */,
|
||||||
D6EE63FB2551F7F60065485C /* StatusCollapseButton.swift in Sources */,
|
D6EE63FB2551F7F60065485C /* StatusCollapseButton.swift in Sources */,
|
||||||
D6CA8CDE296387310050C433 /* SaveToPhotosActivity.swift in Sources */,
|
D6CA8CDE296387310050C433 /* SaveToPhotosActivity.swift in Sources */,
|
||||||
|
@ -2044,7 +2020,6 @@
|
||||||
D6BEA24B291C6A2B002F4D01 /* AlertWithData.swift in Sources */,
|
D6BEA24B291C6A2B002F4D01 /* AlertWithData.swift in Sources */,
|
||||||
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
D61ABEFE28F1C92600B29151 /* FavoriteService.swift in Sources */,
|
||||||
D61F75AB293AF11400C0B37F /* FilterKeywordMO.swift in Sources */,
|
D61F75AB293AF11400C0B37F /* FilterKeywordMO.swift in Sources */,
|
||||||
D65B4B5A29720AB000DABDFB /* ReportStatusView.swift in Sources */,
|
|
||||||
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
D663626221360B1900C9CBA2 /* Preferences.swift in Sources */,
|
||||||
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */,
|
||||||
D627943B23A55BA600D38C68 /* NavigableTableViewCell.swift in Sources */,
|
D627943B23A55BA600D38C68 /* NavigableTableViewCell.swift in Sources */,
|
||||||
|
@ -2090,9 +2065,7 @@
|
||||||
D6FF9860255C717400845181 /* AccountSwitchingContainerViewController.swift in Sources */,
|
D6FF9860255C717400845181 /* AccountSwitchingContainerViewController.swift in Sources */,
|
||||||
D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */,
|
D6E77D0B286D426E00D8B732 /* TrendingLinkCardCollectionViewCell.swift in Sources */,
|
||||||
D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */,
|
D6114E1127F899B30080E273 /* TrendingLinksViewController.swift in Sources */,
|
||||||
D65B4B58297203A700DABDFB /* ReportSelectRulesView.swift in Sources */,
|
|
||||||
D6B81F442560390300F6E31D /* MenuController.swift in Sources */,
|
D6B81F442560390300F6E31D /* MenuController.swift in Sources */,
|
||||||
D65B4B542971F71D00DABDFB /* EditedReport.swift in Sources */,
|
|
||||||
D65234E12561AA68001AF9CF /* NotificationsTableViewController.swift in Sources */,
|
D65234E12561AA68001AF9CF /* NotificationsTableViewController.swift in Sources */,
|
||||||
D6A6C11525B62E9700298D0F /* CacheExpiry.swift in Sources */,
|
D6A6C11525B62E9700298D0F /* CacheExpiry.swift in Sources */,
|
||||||
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */,
|
D67C57AF21E28EAD00C3118B /* Array+Uniques.swift in Sources */,
|
||||||
|
@ -2154,7 +2127,6 @@
|
||||||
D6C82B4125C5BB7E0017F1E6 /* ExploreViewController.swift in Sources */,
|
D6C82B4125C5BB7E0017F1E6 /* ExploreViewController.swift in Sources */,
|
||||||
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
D6B053A423BD2C8100A066FA /* AssetCollectionsListViewController.swift in Sources */,
|
||||||
D6A3A380295515550036B6EF /* ProfileHeaderButton.swift in Sources */,
|
D6A3A380295515550036B6EF /* ProfileHeaderButton.swift in Sources */,
|
||||||
D65B4B562971F98300DABDFB /* ReportView.swift in Sources */,
|
|
||||||
D623A543263634100095BD04 /* PollOptionCheckboxView.swift in Sources */,
|
D623A543263634100095BD04 /* PollOptionCheckboxView.swift in Sources */,
|
||||||
D68A76E829527884001DA1B3 /* PinnedTimelinesView.swift in Sources */,
|
D68A76E829527884001DA1B3 /* PinnedTimelinesView.swift in Sources */,
|
||||||
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */,
|
D690797324A4EF9700023A34 /* UIBezierPath+Helpers.swift in Sources */,
|
||||||
|
@ -2314,7 +2286,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = Tusker/Info.plist;
|
INFOPLIST_FILE = Tusker/Info.plist;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
@ -2382,7 +2354,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
|
@ -2533,7 +2505,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = Tusker/Info.plist;
|
INFOPLIST_FILE = Tusker/Info.plist;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
@ -2562,7 +2534,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = Tusker/Tusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = Tusker/Info.plist;
|
INFOPLIST_FILE = Tusker/Info.plist;
|
||||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
@ -2672,7 +2644,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
|
@ -2698,7 +2670,7 @@
|
||||||
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
CODE_SIGN_ENTITLEMENTS = OpenInTusker/OpenInTusker.entitlements;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 61;
|
CURRENT_PROJECT_VERSION = 60;
|
||||||
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
INFOPLIST_FILE = OpenInTusker/Info.plist;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
"IPHONEOS_DEPLOYMENT_TARGET[sdk=macosx*]" = 14.3;
|
||||||
|
|
|
@ -321,9 +321,7 @@ class MastodonController: ObservableObject {
|
||||||
let request = Client.getCustomEmoji()
|
let request = Client.getCustomEmoji()
|
||||||
run(request) { (response) in
|
run(request) { (response) in
|
||||||
if case let .success(emojis, _) = response {
|
if case let .success(emojis, _) = response {
|
||||||
DispatchQueue.main.async {
|
self.customEmojis = emojis
|
||||||
self.customEmojis = emojis
|
|
||||||
}
|
|
||||||
completion(emojis)
|
completion(emojis)
|
||||||
} else {
|
} else {
|
||||||
completion([])
|
completion([])
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<attribute name="url" attributeType="URI"/>
|
<attribute name="url" attributeType="URI"/>
|
||||||
<attribute name="username" attributeType="String"/>
|
<attribute name="username" attributeType="String"/>
|
||||||
<relationship name="movedTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account"/>
|
<relationship name="movedTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account"/>
|
||||||
<relationship name="relationship" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Relationship" inverseName="account" inverseEntity="Relationship"/>
|
<relationship name="relationship" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Relationship" inverseName="account" inverseEntity="Relationship"/>
|
||||||
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Status" inverseName="account" inverseEntity="Status"/>
|
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Status" inverseName="account" inverseEntity="Status"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
//
|
|
||||||
// EditedReport.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 1/13/23.
|
|
||||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Pachyderm
|
|
||||||
|
|
||||||
class EditedReport: ObservableObject {
|
|
||||||
let accountID: String
|
|
||||||
@Published var statusIDs = [String]()
|
|
||||||
@Published var comment = ""
|
|
||||||
@Published var forward = false
|
|
||||||
@Published var reason: Reason = .spam
|
|
||||||
|
|
||||||
init(accountID: String) {
|
|
||||||
self.accountID = accountID
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeRequest() -> Request<Report>? {
|
|
||||||
let category: String
|
|
||||||
let ruleIDs: [String]
|
|
||||||
switch reason {
|
|
||||||
case .spam:
|
|
||||||
category = "spam"
|
|
||||||
ruleIDs = []
|
|
||||||
case .rules(let ids):
|
|
||||||
category = "violation"
|
|
||||||
ruleIDs = ids
|
|
||||||
}
|
|
||||||
return Client.report(account: accountID, statuses: statusIDs, comment: comment, forward: forward, category: category, ruleIDs: ruleIDs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension EditedReport {
|
|
||||||
enum Reason {
|
|
||||||
case spam
|
|
||||||
case rules([String])
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.accentColor = try container.decodeIfPresent(AccentColor.self, forKey: .accentColor) ?? .default
|
|
||||||
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)
|
||||||
|
@ -91,7 +90,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(accentColor, forKey: .accentColor)
|
|
||||||
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)
|
||||||
|
@ -138,7 +136,6 @@ class Preferences: Codable, ObservableObject {
|
||||||
|
|
||||||
// MARK: Appearance
|
// MARK: Appearance
|
||||||
@Published var theme = UIUserInterfaceStyle.unspecified
|
@Published var theme = UIUserInterfaceStyle.unspecified
|
||||||
@Published var accentColor = AccentColor.default
|
|
||||||
@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
|
||||||
|
@ -199,7 +196,6 @@ class Preferences: Codable, ObservableObject {
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case theme
|
case theme
|
||||||
case accentColor
|
|
||||||
case avatarStyle
|
case avatarStyle
|
||||||
case hideCustomEmojiInUsernames
|
case hideCustomEmojiInUsernames
|
||||||
case showIsStatusReplyIcon
|
case showIsStatusReplyIcon
|
||||||
|
@ -303,83 +299,3 @@ extension Preferences {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension UIUserInterfaceStyle: Codable {}
|
extension UIUserInterfaceStyle: Codable {}
|
||||||
|
|
||||||
extension Preferences {
|
|
||||||
enum AccentColor: String, Codable, CaseIterable {
|
|
||||||
case `default`
|
|
||||||
case purple
|
|
||||||
case indigo
|
|
||||||
case blue
|
|
||||||
case cyan
|
|
||||||
case teal
|
|
||||||
case mint
|
|
||||||
case green
|
|
||||||
// case yellow
|
|
||||||
case orange
|
|
||||||
case red
|
|
||||||
case pink
|
|
||||||
// case brown
|
|
||||||
|
|
||||||
var color: UIColor? {
|
|
||||||
switch self {
|
|
||||||
case .default:
|
|
||||||
return nil
|
|
||||||
case .blue:
|
|
||||||
return .systemBlue
|
|
||||||
// case .brown:
|
|
||||||
// return .systemBrown
|
|
||||||
case .cyan:
|
|
||||||
return .systemCyan
|
|
||||||
case .green:
|
|
||||||
return .systemGreen
|
|
||||||
case .indigo:
|
|
||||||
return .systemIndigo
|
|
||||||
case .mint:
|
|
||||||
return .systemMint
|
|
||||||
case .orange:
|
|
||||||
return .systemOrange
|
|
||||||
case .pink:
|
|
||||||
return .systemPink
|
|
||||||
case .purple:
|
|
||||||
return .systemPurple
|
|
||||||
case .red:
|
|
||||||
return .systemRed
|
|
||||||
case .teal:
|
|
||||||
return .systemTeal
|
|
||||||
// case .yellow:
|
|
||||||
// return .systemYellow
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var name: String {
|
|
||||||
switch self {
|
|
||||||
case .default:
|
|
||||||
return "Default"
|
|
||||||
case .blue:
|
|
||||||
return "Blue"
|
|
||||||
// case .brown:
|
|
||||||
// return "Brown"
|
|
||||||
case .cyan:
|
|
||||||
return "Cyan"
|
|
||||||
case .green:
|
|
||||||
return "Green"
|
|
||||||
case .indigo:
|
|
||||||
return "Indigo"
|
|
||||||
case .mint:
|
|
||||||
return "Mint"
|
|
||||||
case .orange:
|
|
||||||
return "Orange"
|
|
||||||
case .pink:
|
|
||||||
return "Pink"
|
|
||||||
case .purple:
|
|
||||||
return "Purple"
|
|
||||||
case .red:
|
|
||||||
return "Red"
|
|
||||||
case .teal:
|
|
||||||
return "Teal"
|
|
||||||
// case .yellow:
|
|
||||||
// return "Yellow"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -113,6 +113,5 @@ class AuxiliarySceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
@objc private func themePrefChanged() {
|
@objc private func themePrefChanged() {
|
||||||
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
||||||
window?.tintColor = Preferences.shared.accentColor.color
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,6 @@ class ComposeSceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
@objc private func themePrefChanged() {
|
@objc private func themePrefChanged() {
|
||||||
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
||||||
window?.tintColor = Preferences.shared.accentColor.color
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,7 +244,6 @@ class MainSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate
|
||||||
|
|
||||||
@objc func themePrefChanged() {
|
@objc func themePrefChanged() {
|
||||||
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
window?.overrideUserInterfaceStyle = Preferences.shared.theme
|
||||||
window?.tintColor = Preferences.shared.accentColor.color
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func showAddAccount() {
|
func showAddAccount() {
|
||||||
|
|
|
@ -16,8 +16,6 @@ class GalleryPlayerViewController: UIViewController {
|
||||||
|
|
||||||
var attachment: Attachment!
|
var attachment: Attachment!
|
||||||
|
|
||||||
private var isFirstAppearance = true
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
@ -46,13 +44,6 @@ class GalleryPlayerViewController: UIViewController {
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
DispatchQueue.global(qos: .userInitiated).async {
|
||||||
AudioSessionHelper.enable()
|
AudioSessionHelper.enable()
|
||||||
AudioSessionHelper.setVideoPlayback()
|
AudioSessionHelper.setVideoPlayback()
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
if self.isFirstAppearance {
|
|
||||||
self.isFirstAppearance = false
|
|
||||||
self.playerVC.player?.play()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,7 @@ struct MuteAccountView: View {
|
||||||
}
|
}
|
||||||
.frame(height: 50)
|
.frame(height: 50)
|
||||||
.listRowBackground(EmptyView())
|
.listRowBackground(EmptyView())
|
||||||
// vertical insets are so the rounded corners fo the section don't affect the avatar
|
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
|
||||||
.listRowInsets(EdgeInsets(top: 5, leading: 0, bottom: 5, trailing: 0))
|
|
||||||
}
|
}
|
||||||
.accessibilityHidden(true)
|
.accessibilityHidden(true)
|
||||||
|
|
||||||
|
|
|
@ -10,20 +10,14 @@ import SwiftUI
|
||||||
struct AppearancePrefsView : View {
|
struct AppearancePrefsView : View {
|
||||||
@ObservedObject var preferences = Preferences.shared
|
@ObservedObject var preferences = Preferences.shared
|
||||||
|
|
||||||
private var theme: Binding<UIUserInterfaceStyle> = Binding(get: {
|
var theme: Binding<UIUserInterfaceStyle> = Binding(get: {
|
||||||
Preferences.shared.theme
|
Preferences.shared.theme
|
||||||
}, set: {
|
}, set: {
|
||||||
Preferences.shared.theme = $0
|
Preferences.shared.theme = $0
|
||||||
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
|
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
|
||||||
})
|
})
|
||||||
private var accentColor: Binding<Preferences.AccentColor> = Binding {
|
|
||||||
Preferences.shared.accentColor
|
|
||||||
} set: {
|
|
||||||
Preferences.shared.accentColor = $0
|
|
||||||
NotificationCenter.default.post(name: .themePreferenceChanged, object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var useCircularAvatars: Binding<Bool> = Binding(get: {
|
var useCircularAvatars: Binding<Bool> = Binding(get: {
|
||||||
Preferences.shared.avatarStyle == .circle
|
Preferences.shared.avatarStyle == .circle
|
||||||
}) {
|
}) {
|
||||||
Preferences.shared.avatarStyle = $0 ? .circle : .roundRect
|
Preferences.shared.avatarStyle = $0 ? .circle : .roundRect
|
||||||
|
@ -31,35 +25,16 @@ struct AppearancePrefsView : View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List {
|
List {
|
||||||
themeSection
|
|
||||||
accountsSection
|
|
||||||
postsSection
|
|
||||||
}
|
|
||||||
.listStyle(InsetGroupedListStyle())
|
|
||||||
.navigationBarTitle(Text("Appearance"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private var themeSection: some View {
|
|
||||||
Section {
|
|
||||||
Picker(selection: theme, label: Text("Theme")) {
|
Picker(selection: theme, label: Text("Theme")) {
|
||||||
Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified)
|
Text("Use System Theme").tag(UIUserInterfaceStyle.unspecified)
|
||||||
Text("Light").tag(UIUserInterfaceStyle.light)
|
Text("Light").tag(UIUserInterfaceStyle.light)
|
||||||
Text("Dark").tag(UIUserInterfaceStyle.dark)
|
Text("Dark").tag(UIUserInterfaceStyle.dark)
|
||||||
}
|
}
|
||||||
|
accountsSection
|
||||||
Picker(selection: accentColor, label: Text("Accent Color")) {
|
postsSection
|
||||||
ForEach(Preferences.AccentColor.allCases, id: \.rawValue) { color in
|
|
||||||
HStack {
|
|
||||||
Text(color.name)
|
|
||||||
if let color = color.color {
|
|
||||||
Spacer()
|
|
||||||
Image(uiImage: UIImage(systemName: "circle.fill")!.withTintColor(color, renderingMode: .alwaysTemplate).withRenderingMode(.alwaysOriginal))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tag(color)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.listStyle(InsetGroupedListStyle())
|
||||||
|
.navigationBarTitle(Text("Appearance"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private var accountsSection: some View {
|
private var accountsSection: some View {
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
//
|
|
||||||
// ReportAddStatusView.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 1/14/23.
|
|
||||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import Pachyderm
|
|
||||||
|
|
||||||
struct ReportAddStatusView: View {
|
|
||||||
@ObservedObject var report: EditedReport
|
|
||||||
let mastodonController: MastodonController
|
|
||||||
|
|
||||||
@Environment(\.dismiss) private var dismiss
|
|
||||||
@State private var statuses: [StatusMO]?
|
|
||||||
@State private var error: Error?
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
statusesListIfLoaded
|
|
||||||
.navigationTitle("Add Posts")
|
|
||||||
}
|
|
||||||
|
|
||||||
@ViewBuilder
|
|
||||||
private var statusesListIfLoaded: some View {
|
|
||||||
if let statuses {
|
|
||||||
List {
|
|
||||||
ForEach(statuses, id: \.id) { status in
|
|
||||||
Button {
|
|
||||||
report.statusIDs.append(status.id)
|
|
||||||
dismiss()
|
|
||||||
} label: {
|
|
||||||
ReportStatusView(status: status, mastodonController: mastodonController)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ProgressView()
|
|
||||||
.progressViewStyle(.circular)
|
|
||||||
.alertWithData("Error Loading Posts", data: $error, actions: { _ in
|
|
||||||
Button("OK") {}
|
|
||||||
}, message: { error in
|
|
||||||
Text(error.localizedDescription)
|
|
||||||
})
|
|
||||||
.task { @MainActor in
|
|
||||||
do {
|
|
||||||
let req = Account.getStatuses(report.accountID, excludeReplies: false, excludeReblogs: true)
|
|
||||||
let (statuses, _) = try await mastodonController.run(req)
|
|
||||||
await mastodonController.persistentContainer.addAll(statuses: statuses)
|
|
||||||
self.statuses = statuses.compactMap { mastodonController.persistentContainer.status(for: $0.id) }
|
|
||||||
} catch {
|
|
||||||
self.error = error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,59 +0,0 @@
|
||||||
//
|
|
||||||
// ReportSelectRulesView.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 1/13/23.
|
|
||||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ReportSelectRulesView: View {
|
|
||||||
@ObservedObject var mastodonController: MastodonController
|
|
||||||
@ObservedObject var report: EditedReport
|
|
||||||
|
|
||||||
var selectedRuleIDs: [String] {
|
|
||||||
get {
|
|
||||||
if case .rules(let ids) = report.reason {
|
|
||||||
return ids
|
|
||||||
} else {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nonmutating set {
|
|
||||||
report.reason = .rules(newValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
init(mastodonController: MastodonController, report: EditedReport) {
|
|
||||||
self.mastodonController = mastodonController
|
|
||||||
self.report = report
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
List(mastodonController.instance.rules!) { rule in
|
|
||||||
Button {
|
|
||||||
if selectedRuleIDs.contains(rule.id) {
|
|
||||||
selectedRuleIDs.removeAll(where: { $0 == rule.id })
|
|
||||||
} else {
|
|
||||||
selectedRuleIDs.append(rule.id)
|
|
||||||
}
|
|
||||||
} label: {
|
|
||||||
HStack {
|
|
||||||
Text(rule.text)
|
|
||||||
.foregroundColor(.primary)
|
|
||||||
Spacer()
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
.foregroundColor(selectedRuleIDs.contains(rule.id) ? .accentColor : .clear)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.navigationTitle("Rules")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//struct ReportSelectRulesView_Previews: PreviewProvider {
|
|
||||||
// static var previews: some View {
|
|
||||||
// ReportSelectRulesView()
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -1,38 +0,0 @@
|
||||||
//
|
|
||||||
// ReportStatusView.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 1/13/23.
|
|
||||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import SwiftSoup
|
|
||||||
|
|
||||||
private var converter = HTMLConverter()
|
|
||||||
|
|
||||||
struct ReportStatusView: View {
|
|
||||||
let status: StatusMO
|
|
||||||
let mastodonController: MastodonController
|
|
||||||
|
|
||||||
private var text: AttributedString {
|
|
||||||
let str = AttributedString(converter.convert(status.content))
|
|
||||||
return str.transformingAttributes(\.link) { transformer in
|
|
||||||
if transformer.value != nil {
|
|
||||||
transformer.replace(with: \.foregroundColor, value: .accentColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
Text(text)
|
|
||||||
|
|
||||||
if !status.attachments.isEmpty {
|
|
||||||
Text("^[\(status.attachments.count) attachments](inflect: true)")
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
.font(.caption.bold())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,172 +0,0 @@
|
||||||
//
|
|
||||||
// ReportView.swift
|
|
||||||
// Tusker
|
|
||||||
//
|
|
||||||
// Created by Shadowfacts on 1/13/23.
|
|
||||||
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
|
|
||||||
struct ReportView: View {
|
|
||||||
|
|
||||||
let account: AccountMO
|
|
||||||
@ObservedObject var mastodonController: MastodonController
|
|
||||||
@StateObject var report: EditedReport
|
|
||||||
|
|
||||||
@Environment(\.dismiss) private var dismiss
|
|
||||||
@ObservedObject private var preferences = Preferences.shared
|
|
||||||
@State private var isReporting = false
|
|
||||||
@State private var error: Error?
|
|
||||||
|
|
||||||
init(report: EditedReport, mastodonController: MastodonController) {
|
|
||||||
self.account = mastodonController.persistentContainer.account(for: report.accountID)!
|
|
||||||
self.mastodonController = mastodonController
|
|
||||||
self._report = StateObject(wrappedValue: report)
|
|
||||||
if mastodonController.instance.rules == nil {
|
|
||||||
report.reason = .spam
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
|
||||||
if #available(iOS 16.0, *) {
|
|
||||||
NavigationStack {
|
|
||||||
navigationViewContent
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NavigationView {
|
|
||||||
navigationViewContent
|
|
||||||
}
|
|
||||||
.navigationViewStyle(.stack)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var navigationViewContent: some View {
|
|
||||||
Form {
|
|
||||||
Section {
|
|
||||||
HStack {
|
|
||||||
ComposeAvatarImageView(url: account.avatar)
|
|
||||||
.frame(width: 50, height: 50)
|
|
||||||
.cornerRadius(preferences.avatarStyle.cornerRadiusFraction * 50)
|
|
||||||
|
|
||||||
VStack(alignment: .leading) {
|
|
||||||
AccountDisplayNameLabel(account: account, textStyle: .headline, emojiSize: 17)
|
|
||||||
Text("@\(account.acct)")
|
|
||||||
.fontWeight(.light)
|
|
||||||
.foregroundColor(.secondary)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.frame(height: 50)
|
|
||||||
.listRowBackground(EmptyView())
|
|
||||||
// vertical insets are so the rounded corners fo the section don't affect the avatar
|
|
||||||
.listRowInsets(EdgeInsets(top: 5, leading: 0, bottom: 5, trailing: 0))
|
|
||||||
}
|
|
||||||
.accessibilityHidden(true)
|
|
||||||
|
|
||||||
Section {
|
|
||||||
Button {
|
|
||||||
report.reason = .spam
|
|
||||||
} label: {
|
|
||||||
HStack {
|
|
||||||
Text("Spam")
|
|
||||||
Spacer()
|
|
||||||
if case .spam = report.reason {
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if mastodonController.instance.rules != nil {
|
|
||||||
NavigationLink {
|
|
||||||
ReportSelectRulesView(mastodonController: mastodonController, report: report)
|
|
||||||
} label: {
|
|
||||||
HStack {
|
|
||||||
Text("Instance Rule")
|
|
||||||
Spacer()
|
|
||||||
if case .rules(_) = report.reason {
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} header: {
|
|
||||||
Text("Reason")
|
|
||||||
}
|
|
||||||
|
|
||||||
Section {
|
|
||||||
ComposeTextView(text: $report.comment, placeholder: Text("Add any additional comments"))
|
|
||||||
.backgroundColor(.clear)
|
|
||||||
.listRowInsets(EdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8))
|
|
||||||
}
|
|
||||||
|
|
||||||
Section {
|
|
||||||
ForEach(report.statusIDs, id: \.self) { id in
|
|
||||||
ReportStatusView(status: mastodonController.persistentContainer.status(for: id)!, mastodonController: mastodonController)
|
|
||||||
}
|
|
||||||
.onDelete { indices in
|
|
||||||
report.statusIDs.remove(atOffsets: indices)
|
|
||||||
}
|
|
||||||
NavigationLink {
|
|
||||||
ReportAddStatusView(report: report, mastodonController: mastodonController)
|
|
||||||
} label: {
|
|
||||||
Label("Add Posts…", systemImage: "plus")
|
|
||||||
.foregroundColor(.accentColor)
|
|
||||||
}
|
|
||||||
} footer: {
|
|
||||||
Text("Attach posts to your report to provide additional context for moderators.")
|
|
||||||
}
|
|
||||||
|
|
||||||
Section {
|
|
||||||
Toggle("Forward", isOn: $report.forward)
|
|
||||||
} footer: {
|
|
||||||
Text("You can choose to anonymously forward your report to the moderators of **\(account.url.host!)**.")
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(action: self.sendReport) {
|
|
||||||
if isReporting {
|
|
||||||
Text("Sending Report")
|
|
||||||
Spacer()
|
|
||||||
ProgressView()
|
|
||||||
.progressViewStyle(.circular)
|
|
||||||
} else {
|
|
||||||
Text("Send Report")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.disabled(isReporting)
|
|
||||||
}
|
|
||||||
.alertWithData("Error Reporting", data: $error, actions: { error in
|
|
||||||
Button("OK") {}
|
|
||||||
}, message: { error in
|
|
||||||
Text(error.localizedDescription)
|
|
||||||
})
|
|
||||||
.navigationTitle("Report \(account.displayOrUserName)")
|
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
|
||||||
.toolbar {
|
|
||||||
ToolbarItem(placement: .cancellationAction) {
|
|
||||||
Button("Cancel") {
|
|
||||||
self.dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func sendReport() {
|
|
||||||
isReporting = true
|
|
||||||
Task {
|
|
||||||
do {
|
|
||||||
_ = try await mastodonController.run(report.makeRequest()!)
|
|
||||||
self.dismiss()
|
|
||||||
} catch {
|
|
||||||
self.error = error
|
|
||||||
self.isReporting = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//struct ReportView_Previews: PreviewProvider {
|
|
||||||
// static var previews: some View {
|
|
||||||
// ReportView()
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -334,31 +334,25 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
loadViewIfNeeded()
|
loadViewIfNeeded()
|
||||||
var loaded = false
|
|
||||||
await controller.restoreInitial {
|
await controller.restoreInitial {
|
||||||
let hasStatusesToRestore = await loadStatusesToRestore(position: position)
|
await loadStatusesToRestore(position: position)
|
||||||
if hasStatusesToRestore {
|
applyItemsToRestore(position: position)
|
||||||
applyItemsToRestore(position: position)
|
|
||||||
loaded = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return loaded
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private func loadStatusesToRestore(position: TimelinePosition) async -> Bool {
|
private func loadStatusesToRestore(position: TimelinePosition) async {
|
||||||
let unloaded = position.statusIDs.filter({ mastodonController.persistentContainer.status(for: $0) == nil })
|
let unloaded = position.statusIDs.filter({ mastodonController.persistentContainer.status(for: $0) == nil })
|
||||||
guard !unloaded.isEmpty else {
|
guard !unloaded.isEmpty else {
|
||||||
return true
|
return
|
||||||
}
|
}
|
||||||
let statuses = await withTaskGroup(of: Status?.self) { group -> [Status] in
|
let statuses = await withTaskGroup(of: Status?.self) { group -> [Status] in
|
||||||
for id in unloaded {
|
for id in unloaded {
|
||||||
group.addTask {
|
group.addTask { @MainActor in
|
||||||
do {
|
if let (status, _) = try? await self.mastodonController.run(Client.getStatus(id: id)) {
|
||||||
let (status, _) = try await self.mastodonController.run(Client.getStatus(id: id))
|
|
||||||
return status
|
return status
|
||||||
} catch {
|
} else {
|
||||||
print(error)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -370,20 +364,6 @@ class TimelineViewController: UIViewController, TimelineLikeCollectionViewContro
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await mastodonController.persistentContainer.addAll(statuses: statuses, in: mastodonController.persistentContainer.viewContext)
|
await mastodonController.persistentContainer.addAll(statuses: statuses, in: mastodonController.persistentContainer.viewContext)
|
||||||
|
|
||||||
// update the timeline position in case some statuses couldn't be loaded
|
|
||||||
if let center = position.centerStatusID {
|
|
||||||
let nearestLoadedStatusToCenter = position.statusIDs[position.statusIDs.firstIndex(of: center)!...].first(where: { id in
|
|
||||||
// was already loaded or was just now loaded
|
|
||||||
!unloaded.contains(id) || statuses.contains(where: { $0.id == id })
|
|
||||||
})
|
|
||||||
position.centerStatusID = nearestLoadedStatusToCenter
|
|
||||||
}
|
|
||||||
position.statusIDs = position.statusIDs.filter { id in
|
|
||||||
!unloaded.contains(id) || statuses.contains(where: { $0.id == id })
|
|
||||||
}
|
|
||||||
|
|
||||||
return !position.statusIDs.isEmpty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func applyItemsToRestore(position: TimelinePosition) {
|
private func applyItemsToRestore(position: TimelinePosition) {
|
||||||
|
|
|
@ -95,10 +95,7 @@ class TimelinesPageViewController: SegmentedPageViewController<TimelinesPageView
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let page = Page(mastodonController: mastodonController, timeline: timeline)
|
let page = Page(mastodonController: mastodonController, timeline: timeline)
|
||||||
// the pinned timelines may have changed after an iCloud sync, in which case don't restore anything
|
selectPage(page, animated: false)
|
||||||
if pages.contains(page) {
|
|
||||||
selectPage(page, animated: false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func customizePressed() {
|
@objc private func customizePressed() {
|
||||||
|
|
|
@ -84,11 +84,6 @@ extension MenuActionProvider {
|
||||||
}))
|
}))
|
||||||
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.blockAction(for: $0, mastodonController: $1) }))
|
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.blockAction(for: $0, mastodonController: $1) }))
|
||||||
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.muteAction(for: $0, mastodonController: $1) }))
|
suppressSection.append(relationshipAction(fetchRelationship, accountID: accountID, mastodonController: mastodonController, builder: { [unowned self] in self.muteAction(for: $0, mastodonController: $1) }))
|
||||||
suppressSection.append(createAction(identifier: "report", title: "Report", systemImageName: "flag", handler: { [unowned self] _ in
|
|
||||||
let view = ReportView(report: EditedReport(accountID: accountID), mastodonController: mastodonController)
|
|
||||||
let host = UIHostingController(rootView: view)
|
|
||||||
self.navigationDelegate?.present(host, animated: true)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showProfileActivity(id: accountID, accountID: loggedInAccountID))
|
addOpenInNewWindow(actions: &shareSection, activity: UserActivityManager.showProfileActivity(id: accountID, accountID: loggedInAccountID))
|
||||||
|
@ -215,15 +210,7 @@ extension MenuActionProvider {
|
||||||
}), at: 1)
|
}), at: 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var actionsSection: [UIAction] = [
|
var actionsSection: [UIAction] = []
|
||||||
createAction(identifier: "report", title: "Report", systemImageName: "flag", handler: { [weak self] _ in
|
|
||||||
let report = EditedReport(accountID: status.account.id)
|
|
||||||
report.statusIDs = [status.id]
|
|
||||||
let view = ReportView(report: report, mastodonController: mastodonController)
|
|
||||||
let host = UIHostingController(rootView: view)
|
|
||||||
self?.navigationDelegate?.present(host, animated: true)
|
|
||||||
})
|
|
||||||
]
|
|
||||||
|
|
||||||
if includeStatusButtonActions {
|
if includeStatusButtonActions {
|
||||||
actionsSection.insert(createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in
|
actionsSection.insert(createAction(identifier: "reply", title: "Reply", systemImageName: "arrowshape.turn.up.left", handler: { [weak self] (_) in
|
||||||
|
|
|
@ -55,8 +55,6 @@ class PollFinishedTableViewCell: UITableViewCell {
|
||||||
let doc = try! SwiftSoup.parseBodyFragment(status.content)
|
let doc = try! SwiftSoup.parseBodyFragment(status.content)
|
||||||
statusContentLabel.text = try! doc.text()
|
statusContentLabel.text = try! doc.text()
|
||||||
|
|
||||||
pollView.mastodonController = mastodonController
|
|
||||||
pollView.toastableViewController = delegate
|
|
||||||
pollView.updateUI(status: status, poll: poll)
|
pollView.updateUI(status: status, poll: poll)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,12 +48,12 @@ class BaseStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
private var favorited = false {
|
private var favorited = false {
|
||||||
didSet {
|
didSet {
|
||||||
favoriteButton.tintColor = favorited ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : .tintColor
|
favoriteButton.tintColor = favorited ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : tintColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private var reblogged = false {
|
private var reblogged = false {
|
||||||
didSet {
|
didSet {
|
||||||
reblogButton.tintColor = reblogged ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : .tintColor
|
reblogButton.tintColor = reblogged ? UIColor(displayP3Red: 1, green: 0.8, blue: 0, alpha: 1) : tintColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8r8-O8-Agh" customClass="StatusCollapseButton" customModule="Tusker" customModuleProvider="target">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8r8-O8-Agh" customClass="StatusCollapseButton" customModule="Tusker" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="86.5" width="361" height="30"/>
|
<rect key="frame" x="0.0" y="86.5" width="361" height="30"/>
|
||||||
<color key="backgroundColor" systemColor="tintColor"/>
|
<color key="backgroundColor" systemColor="systemBlueColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" constant="30" id="icD-3q-uJ6"/>
|
<constraint firstAttribute="height" constant="30" id="icD-3q-uJ6"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
@ -169,7 +169,6 @@
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2cc-lE-AdG">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2cc-lE-AdG">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="90.5" height="26"/>
|
<rect key="frame" x="0.0" y="0.0" width="90.5" height="26"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Reply"/>
|
<accessibility key="accessibilityConfiguration" label="Reply"/>
|
||||||
<color key="tintColor" systemColor="tintColor"/>
|
|
||||||
<state key="normal">
|
<state key="normal">
|
||||||
<imageReference key="image" image="arrowshape.turn.up.left.fill" catalog="system" symbolScale="large"/>
|
<imageReference key="image" image="arrowshape.turn.up.left.fill" catalog="system" symbolScale="large"/>
|
||||||
</state>
|
</state>
|
||||||
|
@ -180,7 +179,6 @@
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DhN-rJ-jdA">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DhN-rJ-jdA">
|
||||||
<rect key="frame" x="90.5" y="0.0" width="90" height="26"/>
|
<rect key="frame" x="90.5" y="0.0" width="90" height="26"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Favorite"/>
|
<accessibility key="accessibilityConfiguration" label="Favorite"/>
|
||||||
<color key="tintColor" systemColor="tintColor"/>
|
|
||||||
<state key="normal">
|
<state key="normal">
|
||||||
<imageReference key="image" image="star.fill" catalog="system" symbolScale="large"/>
|
<imageReference key="image" image="star.fill" catalog="system" symbolScale="large"/>
|
||||||
</state>
|
</state>
|
||||||
|
@ -191,7 +189,6 @@
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GUG-f7-Hdy">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="GUG-f7-Hdy">
|
||||||
<rect key="frame" x="180.5" y="0.0" width="90.5" height="26"/>
|
<rect key="frame" x="180.5" y="0.0" width="90.5" height="26"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="Reblog"/>
|
<accessibility key="accessibilityConfiguration" label="Reblog"/>
|
||||||
<color key="tintColor" systemColor="tintColor"/>
|
|
||||||
<state key="normal">
|
<state key="normal">
|
||||||
<imageReference key="image" image="repeat" catalog="system" symbolScale="large"/>
|
<imageReference key="image" image="repeat" catalog="system" symbolScale="large"/>
|
||||||
</state>
|
</state>
|
||||||
|
@ -202,7 +199,6 @@
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ujo-Ap-dmK">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" pointerInteraction="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ujo-Ap-dmK">
|
||||||
<rect key="frame" x="271" y="0.0" width="90" height="26"/>
|
<rect key="frame" x="271" y="0.0" width="90" height="26"/>
|
||||||
<accessibility key="accessibilityConfiguration" label="More Actions"/>
|
<accessibility key="accessibilityConfiguration" label="More Actions"/>
|
||||||
<color key="tintColor" systemColor="tintColor"/>
|
|
||||||
<state key="normal">
|
<state key="normal">
|
||||||
<imageReference key="image" image="ellipsis" catalog="system" symbolScale="large"/>
|
<imageReference key="image" image="ellipsis" catalog="system" symbolScale="large"/>
|
||||||
</state>
|
</state>
|
||||||
|
@ -282,7 +278,7 @@
|
||||||
<systemColor name="systemBackgroundColor">
|
<systemColor name="systemBackgroundColor">
|
||||||
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
<systemColor name="tintColor">
|
<systemColor name="systemBlueColor">
|
||||||
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</systemColor>
|
</systemColor>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -668,7 +668,6 @@ class TimelineStatusCollectionViewCell: UICollectionViewListCell, StatusCollecti
|
||||||
|
|
||||||
@objc private func preferencesChanged() {
|
@objc private func preferencesChanged() {
|
||||||
guard let mastodonController,
|
guard let mastodonController,
|
||||||
let statusID,
|
|
||||||
let status = mastodonController.persistentContainer.status(for: statusID) else {
|
let status = mastodonController.persistentContainer.status(for: statusID) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class ToastView: UIView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupView() {
|
private func setupView() {
|
||||||
backgroundColor = .tintColor
|
backgroundColor = .systemBlue
|
||||||
layer.shadowColor = UIColor.black.cgColor
|
layer.shadowColor = UIColor.black.cgColor
|
||||||
layer.shadowRadius = 5
|
layer.shadowRadius = 5
|
||||||
layer.shadowOffset = CGSize(width: 0, height: 2.5)
|
layer.shadowOffset = CGSize(width: 0, height: 2.5)
|
||||||
|
|
Loading…
Reference in New Issue