Refactoring and bug fixes.

This commit is contained in:
Marcin Czachursk 2023-03-15 14:27:59 +01:00
parent a13265ca8f
commit 93734579a4
33 changed files with 94 additions and 76 deletions

View File

@ -9,5 +9,4 @@ import CoreData
@objc(AccountData)
public class AccountData: NSManagedObject {
}

View File

@ -51,9 +51,7 @@ extension AccountData {
@objc(removeStatuses:)
@NSManaged public func removeFromStatuses(_ values: NSSet)
}
extension AccountData : Identifiable {
}

View File

@ -24,7 +24,7 @@ class AccountDataHandler {
func getCurrentAccountData(viewContext: NSManagedObjectContext? = nil) -> AccountData? {
let accounts = self.getAccountsData(viewContext: viewContext)
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
let currentAccount = accounts.first { accountData in
accountData.id == defaultSettings.currentAccount

View File

@ -9,5 +9,4 @@ import CoreData
@objc(ApplicationSettings)
public class ApplicationSettings: NSManagedObject {
}

View File

@ -30,5 +30,4 @@ extension ApplicationSettings {
}
extension ApplicationSettings : Identifiable {
}

View File

@ -10,7 +10,7 @@ class ApplicationSettingsHandler {
public static let shared = ApplicationSettingsHandler()
private init() { }
func getDefaultSettings() -> ApplicationSettings {
func get() -> ApplicationSettings {
var settingsList: [ApplicationSettings] = []
let context = CoreDataHandler.shared.container.viewContext
@ -34,69 +34,69 @@ class ApplicationSettingsHandler {
}
}
func setAccountAsDefault(accountData: AccountData?) {
let defaultSettings = self.getDefaultSettings()
func set(accountData: AccountData?) {
let defaultSettings = self.get()
defaultSettings.currentAccount = accountData?.id
CoreDataHandler.shared.save()
}
func setDefaultTintColor(tintColor: TintColor) {
let defaultSettings = self.getDefaultSettings()
func set(tintColor: TintColor) {
let defaultSettings = self.get()
defaultSettings.tintColor = Int32(tintColor.rawValue)
CoreDataHandler.shared.save()
}
func setDefaultTheme(theme: Theme) {
let defaultSettings = self.getDefaultSettings()
func set(theme: Theme) {
let defaultSettings = self.get()
defaultSettings.theme = Int32(theme.rawValue)
CoreDataHandler.shared.save()
}
func setDefaultAvatarShape(avatarShape: AvatarShape) {
let defaultSettings = self.getDefaultSettings()
func set(avatarShape: AvatarShape) {
let defaultSettings = self.get()
defaultSettings.avatarShape = Int32(avatarShape.rawValue)
CoreDataHandler.shared.save()
}
func setHapticTabSelectionEnabled(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.hapticTabSelectionEnabled = value
func set(hapticTabSelectionEnabled: Bool) {
let defaultSettings = self.get()
defaultSettings.hapticTabSelectionEnabled = hapticTabSelectionEnabled
CoreDataHandler.shared.save()
}
func setHapticRefreshEnabled(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.hapticRefreshEnabled = value
func set(hapticRefreshEnabled: Bool) {
let defaultSettings = self.get()
defaultSettings.hapticRefreshEnabled = hapticRefreshEnabled
CoreDataHandler.shared.save()
}
func setHapticAnimationEnabled(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.hapticAnimationEnabled = value
func set(hapticAnimationEnabled: Bool) {
let defaultSettings = self.get()
defaultSettings.hapticAnimationEnabled = hapticAnimationEnabled
CoreDataHandler.shared.save()
}
func setHapticNotificationEnabled(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.hapticNotificationEnabled = value
func set(hapticNotificationEnabled: Bool) {
let defaultSettings = self.get()
defaultSettings.hapticNotificationEnabled = hapticNotificationEnabled
CoreDataHandler.shared.save()
}
func setHapticButtonPressEnabled(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.hapticButtonPressEnabled = value
func set(hapticButtonPressEnabled: Bool) {
let defaultSettings = self.get()
defaultSettings.hapticButtonPressEnabled = hapticButtonPressEnabled
CoreDataHandler.shared.save()
}
func setShowSensitive(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.showSensitive = value
func set(showSensitive: Bool) {
let defaultSettings = self.get()
defaultSettings.showSensitive = showSensitive
CoreDataHandler.shared.save()
}
func setShowPhotoDescription(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.showPhotoDescription = value
func set(showPhotoDescription: Bool) {
let defaultSettings = self.get()
defaultSettings.showPhotoDescription = showPhotoDescription
CoreDataHandler.shared.save()
}

View File

@ -9,5 +9,4 @@ import CoreData
@objc(AttachmentData)
public class AttachmentData: NSManagedObject {
}

View File

@ -33,5 +33,4 @@ extension AttachmentData {
}
extension AttachmentData : Identifiable {
}

View File

@ -9,5 +9,4 @@ import CoreData
@objc(StatusData)
public class StatusData: NSManagedObject {
}

View File

@ -65,5 +65,4 @@ extension StatusData {
}
extension StatusData : Identifiable {
}

View File

@ -12,6 +12,11 @@
"global.error.errorDuringImageDownload" = "Cannot download image.";
"global.error.canceledImageDownload" = "Download image has been canceled.";
"global.error.errorDuringDataLoad" = "Loading data failed.";
"global.error.errorDuringUserRead" = "Cannot retrieve user account.";
"global.error.badUrlServer" = "Bad url to server.";
"global.error.accessTokenNotFound" = "Access token not found.";
"global.error.errorDuringDownloadStatus" = "Error during download status from server.";
"global.error.errorDuringPurchaseVerification" = "Purchase verification failed.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Home";

View File

@ -12,6 +12,11 @@
"global.error.errorDuringImageDownload" = "Błąd podczas pobierania zdjęcia.";
"global.error.canceledImageDownload" = "Pobieranie zdjęcia zostało anulowane.";
"global.error.errorDuringDataLoad" = "Błąd podczas pobierania danych.";
"global.error.errorDuringUserRead" = "Błąd podczas odczytu danych użytkownika.";
"global.error.badUrlServer" = "Niepoprawny adres serwera.";
"global.error.accessTokenNotFound" = "Brak tokenu dostępu.";
"global.error.errorDuringDownloadStatus" = "Błąd podczas pobierania statusu.";
"global.error.errorDuringPurchaseVerification" = "Błąd podczas weryfikacji płatności.";
// MARK: Main view (main navigation bar).
"mainview.tab.homeTimeline" = "Główna";
@ -220,7 +225,7 @@
"status.error.loadingCommentsFailed" =" Błąd podczas wczytywanie komentarzy.";
"status.error.reboostFailed" = "Błąd podczas podbijania.";
"status.error.favouriteFailed" = "Błąd podczas polubiania.";
"status.error.bookmarkFailed" = "Błąd podczas dodawania/uzuwania z zakładek.";
"status.error.bookmarkFailed" = "Błąd podczas dodawania/usuwania z zakładek.";
"status.error.deleteFailed" = "Błąd podczas usuwania.";
// Mark: Accounts view.

View File

@ -5,6 +5,7 @@ import PackageDescription
let package = Package(
name: "PixelfedKit",
defaultLocalization: "en",
platforms: [
.iOS(.v16),
.macOS(.v12),

View File

@ -38,11 +38,14 @@ public struct Html: Codable {
}
private func parseToMarkdown(html: String) throws -> String {
// Fix issue: https://github.com/VernissageApp/Home/issues/11
let mutatedHtml = html
// Fix issue: https://github.com/VernissageApp/Home/issues/11
// First we have to replace <br />/n into single <br /> (new line is skipped by HTML but this causes empty space in HTML2Markdown.
.replacingOccurrences(of: "<br />\n", with: "<br />")
.replacingOccurrences(of: "<br/>\n", with: "<br />")
// Fix issue: https://github.com/VernissageApp/Home/issues/10
// When we replace all <br />\n into single <br /> then we have to change the remaining \n into <br />
.replacingOccurrences(of: "\n", with: "<br />")
let dom = try HTMLParser().parse(html: mutatedHtml)
return dom.toMarkdown()

View File

@ -17,9 +17,15 @@ extension NetworkError: LocalizedError {
case .notSuccessResponse(let response):
let statusCode = response.statusCode()
return NSLocalizedString("Server response: '\(statusCode?.localizedDescription ?? "unknown")'.", comment: "It's error returned from remote server. Request URL: '\(response.url?.string ?? "unknown")'.")
let localizedString = NSLocalizedString("global.error.notSuccessResponse",
bundle: Bundle.module,
comment: "It's error returned from remote server. Request URL: '\(response.url?.string ?? "unknown")'.")
return String(format: localizedString, statusCode?.localizedDescription ?? "unknown")
case .unknownError:
return NSLocalizedString("Unkonwn network error.", comment: "Response doesn't contains any information about request status.")
return NSLocalizedString("global.error.unknownError",
bundle: Bundle.module,
comment: "Response doesn't contains any information about request status.")
}
}
}

View File

@ -0,0 +1,3 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Server response: %@.";
"global.error.unknownError" = "Unexpected error.";

View File

@ -0,0 +1,3 @@
// MARK: Network errors.
"global.error.notSuccessResponse" = "Odpowiedź serwera: %@.";
"global.error.unknownError" = "Nieznany błąd serwera.";

View File

@ -1261,7 +1261,7 @@
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71;
CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@ -1289,7 +1289,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71;
CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@ -1435,7 +1435,7 @@
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71;
CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1473,7 +1473,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71;
CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;

View File

@ -15,9 +15,9 @@ extension AuthorisationError: LocalizedError {
public var errorDescription: String? {
switch self {
case .badServerUrl:
return NSLocalizedString("Bad url to server.", comment: "User enter bad URL to server.")
return NSLocalizedString("global.error.badUrlServer", comment: "User enter bad URL to server.")
case .accessTokenNotFound:
return NSLocalizedString("Acess token not found.", comment: "Access token is not saved in account model.")
return NSLocalizedString("global.error.accessTokenNotFound", comment: "Access token is not saved in account model.")
}
}
}

View File

@ -14,7 +14,7 @@ extension ClientError: LocalizedError {
public var errorDescription: String? {
switch self {
case .cannotRetrieveStatus:
return NSLocalizedString("Cannot retrieve status", comment: "Status cannot be downloaded from server.")
return NSLocalizedString("global.error.errorDuringDownloadStatus", comment: "Status cannot be downloaded from server.")
}
}
}

View File

@ -14,7 +14,7 @@ extension DatabaseError: LocalizedError {
public var errorDescription: String? {
switch self {
case .cannotDownloadAccount:
return NSLocalizedString("Cannot retrieve user account.", comment: "User acount cannot be downloaded from Core Data.")
return NSLocalizedString("global.error.errorDuringUserRead", comment: "User acount cannot be downloaded from Core Data.")
}
}
}

View File

@ -16,7 +16,7 @@ extension PurchaseError: LocalizedError {
public var errorDescription: String? {
switch self {
case .failedVerification:
return NSLocalizedString("Purchase verification failed.", comment: "Something went wrong during purchase verification.")
return NSLocalizedString("global.error.errorDuringPurchaseVerification", comment: "Something went wrong during purchase verification.")
case .system(let error):
return error.localizedDescription
}

View File

@ -113,7 +113,7 @@ public class AuthorizationService {
}
// Set newly created account as current (only when we create a first account).
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
if defaultSettings.currentAccount == nil {
defaultSettings.currentAccount = accountData.id
}

View File

@ -137,7 +137,7 @@ struct VernissageApp: App {
}
private func loadUserPreferences() {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
if let tintColor = TintColor(rawValue: Int(defaultSettings.tintColor)) {
self.applicationState.tintColor = tintColor
@ -174,7 +174,7 @@ struct VernissageApp: App {
}
private func refreshAccessTokens() async {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
// Run refreshing access tokens once per day.
guard let refreshTokenDate = Calendar.current.date(byAdding: .day, value: 1, to: defaultSettings.lastRefreshTokens), refreshTokenDate < Date.now else {

View File

@ -86,6 +86,7 @@ struct ImageUploadView: View {
if let photoData = self.photoAttachment.photoData, let uiImage = UIImage(data: photoData) {
Image(uiImage: uiImage)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 80, height: 80)
} else {
Rectangle()

View File

@ -343,7 +343,7 @@ struct MainView: View {
lastSeenStatusId: accountData.lastSeenStatusId)
// Set account as default (application will open this account after restart).
ApplicationSettingsHandler.shared.setAccountAsDefault(accountData: accountData)
ApplicationSettingsHandler.shared.set(accountData: accountData)
}
}
}

View File

@ -23,7 +23,7 @@ struct AccentsSectionView: View {
.frame(width: 36, height: 36)
.onTapGesture {
self.applicationState.tintColor = color
ApplicationSettingsHandler.shared.setDefaultTintColor(tintColor: color)
ApplicationSettingsHandler.shared.set(tintColor: color)
}
if color == self.applicationState.tintColor {
Image(systemName: "checkmark")
@ -47,7 +47,7 @@ struct AccentsSectionView: View {
.frame(width: 36, height: 36)
.onTapGesture {
self.applicationState.tintColor = color
ApplicationSettingsHandler.shared.setDefaultTintColor(tintColor: color)
ApplicationSettingsHandler.shared.set(tintColor: color)
}
if color == self.applicationState.tintColor {
Image(systemName: "checkmark")

View File

@ -72,7 +72,7 @@ struct AccountsSectionView: View {
if shouldClearApplicationState {
// We have to do this after animation of deleting row is ended.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
ApplicationSettingsHandler.shared.setAccountAsDefault(accountData: nil)
ApplicationSettingsHandler.shared.set(accountData: nil)
self.applicationState.clearApplicationState()
self.client.clearAccount()
}

View File

@ -13,7 +13,7 @@ struct AvatarShapesSectionView: View {
Section("settings.title.avatar") {
Button {
self.applicationState.avatarShape = .circle
ApplicationSettingsHandler.shared.setDefaultAvatarShape(avatarShape: .circle)
ApplicationSettingsHandler.shared.set(avatarShape: .circle)
} label: {
HStack {
Image("Avatar")
@ -35,7 +35,7 @@ struct AvatarShapesSectionView: View {
Button {
self.applicationState.avatarShape = .roundedRectangle
ApplicationSettingsHandler.shared.setDefaultAvatarShape(avatarShape: .roundedRectangle)
ApplicationSettingsHandler.shared.set(avatarShape: .roundedRectangle)
} label: {
HStack {
Image("Avatar")

View File

@ -22,35 +22,35 @@ struct HapticsSectionView: View {
Toggle("settings.title.hapticsTabSelection", isOn: $hapticTabSelectionEnabled)
.onChange(of: hapticTabSelectionEnabled) { newValue in
self.applicationState.hapticTabSelectionEnabled = newValue
ApplicationSettingsHandler.shared.setHapticTabSelectionEnabled(value: newValue)
ApplicationSettingsHandler.shared.set(hapticTabSelectionEnabled: newValue)
}
Toggle("settings.title.hapticsButtonPress", isOn: $hapticButtonPressEnabled)
.onChange(of: hapticButtonPressEnabled) { newValue in
self.applicationState.hapticButtonPressEnabled = newValue
ApplicationSettingsHandler.shared.setHapticButtonPressEnabled(value: newValue)
ApplicationSettingsHandler.shared.set(hapticButtonPressEnabled: newValue)
}
Toggle("settings.title.hapticsListRefresh", isOn: $hapticRefreshEnabled)
.onChange(of: hapticRefreshEnabled) { newValue in
self.applicationState.hapticRefreshEnabled = newValue
ApplicationSettingsHandler.shared.setHapticRefreshEnabled(value: newValue)
ApplicationSettingsHandler.shared.set(hapticRefreshEnabled: newValue)
}
Toggle("settings.title.hapticsAnimationFinished", isOn: $hapticAnimationEnabled)
.onChange(of: hapticAnimationEnabled) { newValue in
self.applicationState.hapticAnimationEnabled = newValue
ApplicationSettingsHandler.shared.setHapticAnimationEnabled(value: newValue)
ApplicationSettingsHandler.shared.set(hapticAnimationEnabled: newValue)
}
// Toggle("Notification", isOn: $hapticNotificationEnabled)
// .onChange(of: hapticNotificationEnabled) { newValue in
// self.applicationState.hapticNotificationEnabled = newValue
// ApplicationSettingsHandler.shared.setHapticNotificationEnabled(value: newValue)
// ApplicationSettingsHandler.shared.set(hapticNotificationEnabled: newValue)
// }
}
.onAppear {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
self.hapticTabSelectionEnabled = defaultSettings.hapticTabSelectionEnabled
self.hapticButtonPressEnabled = defaultSettings.hapticButtonPressEnabled
self.hapticRefreshEnabled = defaultSettings.hapticRefreshEnabled

View File

@ -26,7 +26,7 @@ struct MediaSettingsView: View {
}
.onChange(of: showSensitive) { newValue in
self.applicationState.showSensitive = newValue
ApplicationSettingsHandler.shared.setShowSensitive(value: newValue)
ApplicationSettingsHandler.shared.set(showSensitive: newValue)
}
Toggle(isOn: $showPhotoDescription) {
@ -39,11 +39,11 @@ struct MediaSettingsView: View {
}
.onChange(of: showPhotoDescription) { newValue in
self.applicationState.showPhotoDescription = newValue
ApplicationSettingsHandler.shared.setShowPhotoDescription(value: newValue)
ApplicationSettingsHandler.shared.set(showPhotoDescription: newValue)
}
}
.onAppear {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
self.showSensitive = defaultSettings.showSensitive
self.showPhotoDescription = defaultSettings.showPhotoDescription
}

View File

@ -14,7 +14,7 @@ struct ThemeSectionView: View {
Section("settings.title.theme") {
Button {
self.applicationState.theme = .system
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .system)
ApplicationSettingsHandler.shared.set(theme: .system)
} label: {
HStack {
Text("settings.title.system", comment: "System")
@ -28,7 +28,7 @@ struct ThemeSectionView: View {
Button {
self.applicationState.theme = .light
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .light)
ApplicationSettingsHandler.shared.set(theme: .light)
} label: {
HStack {
Text("settings.title.light", comment: "Light")
@ -42,7 +42,7 @@ struct ThemeSectionView: View {
Button {
self.applicationState.theme = .dark
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .dark)
ApplicationSettingsHandler.shared.set(theme: .dark)
} label: {
HStack {
Text("settings.title.dark", comment: "Dark")

View File

@ -15,7 +15,7 @@ public class ImageFetcher {
private let maxImageSize = 1000.0
func fetchWidgetEntries(length: Int = 8) async throws -> [WidgetEntry] {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
let defaultSettings = ApplicationSettingsHandler.shared.get()
guard let accountId = defaultSettings.currentAccount else {
return [self.placeholder()]
}