diff --git a/CoreData/CoreDataHandler.swift b/CoreData/CoreDataHandler.swift index 56a9d54..513c78c 100644 --- a/CoreData/CoreDataHandler.swift +++ b/CoreData/CoreDataHandler.swift @@ -64,6 +64,7 @@ public class CoreDataHandler { } }) + container.viewContext.automaticallyMergesChangesFromParent = true return container }() diff --git a/Vernissage.xcodeproj/project.pbxproj b/Vernissage.xcodeproj/project.pbxproj index 095fca7..21a41be 100644 --- a/Vernissage.xcodeproj/project.pbxproj +++ b/Vernissage.xcodeproj/project.pbxproj @@ -1221,7 +1221,7 @@ CODE_SIGN_ENTITLEMENTS = VernissageWidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 64; + CURRENT_PROJECT_VERSION = 65; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1249,7 +1249,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = VernissageWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 64; + CURRENT_PROJECT_VERSION = 65; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1393,7 +1393,7 @@ CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 64; + CURRENT_PROJECT_VERSION = 65; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; @@ -1431,7 +1431,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 64; + CURRENT_PROJECT_VERSION = 65; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; diff --git a/VernissageWidget/Assets.xcassets/Avatar.imageset/Avatar.png b/VernissageWidget/Assets.xcassets/Avatar.imageset/Avatar.png new file mode 100644 index 0000000..ffc46a5 Binary files /dev/null and b/VernissageWidget/Assets.xcassets/Avatar.imageset/Avatar.png differ diff --git a/VernissageWidget/Assets.xcassets/Avatar.imageset/Contents.json b/VernissageWidget/Assets.xcassets/Avatar.imageset/Contents.json new file mode 100644 index 0000000..08ba029 --- /dev/null +++ b/VernissageWidget/Assets.xcassets/Avatar.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Avatar.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/VernissageWidget/Assets.xcassets/Placeholder.imageset/Contents.json b/VernissageWidget/Assets.xcassets/Placeholder.imageset/Contents.json new file mode 100644 index 0000000..783a1d6 --- /dev/null +++ b/VernissageWidget/Assets.xcassets/Placeholder.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "Placeholder.jpg", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/VernissageWidget/Assets.xcassets/Placeholder.imageset/Placeholder.jpg b/VernissageWidget/Assets.xcassets/Placeholder.imageset/Placeholder.jpg new file mode 100644 index 0000000..f19c1f8 Binary files /dev/null and b/VernissageWidget/Assets.xcassets/Placeholder.imageset/Placeholder.jpg differ diff --git a/VernissageWidget/ImageFetcher.swift b/VernissageWidget/ImageFetcher.swift index b5728be..7ef1487 100644 --- a/VernissageWidget/ImageFetcher.swift +++ b/VernissageWidget/ImageFetcher.swift @@ -71,7 +71,7 @@ public class ImageFetcher { } func placeholder() -> WidgetEntry { - WidgetEntry(date: Date(), image: nil, avatar: nil, displayName: "John Misiakiewiczowicz", statusId: "123321") + WidgetEntry(date: Date(), image: nil, avatar: nil, displayName: "Caroline Rick", statusId: "") } private func getImage(url: URL?) async -> UIImage? { diff --git a/VernissageWidget/Views/LargeWidgetView.swift b/VernissageWidget/Views/LargeWidgetView.swift index ef834fd..9cd80ee 100644 --- a/VernissageWidget/Views/LargeWidgetView.swift +++ b/VernissageWidget/Views/LargeWidgetView.swift @@ -12,42 +12,44 @@ struct LargeWidgetView: View { var body: some View { if let uiImage = entry.image, let uiAvatar = entry.avatar { - VStack { - Spacer() - HStack { - Image(uiImage: uiAvatar) - .resizable() - .clipShape(Circle()) - .aspectRatio(contentMode: .fit) - .frame(width: 44, height: 44) - - Text(entry.displayName ?? "") - Spacer() - } - .padding(.leading, 8) - .padding(.bottom, 8) - } - .background { - Image(uiImage: uiImage) - .resizable() - .aspectRatio(contentMode: .fill) - .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) - } + self.getWidgetBody(uiImage: Image(uiImage: uiImage), uiAvatar: Image(uiImage: uiAvatar)) } else { - VStack { - Spacer() - HStack { - Circle() - .foregroundColor(Color(UIColor.placeholderText)) - .frame(width: 44, height: 44) + self.getWidgetBody(uiImage: Image("Placeholder"), uiAvatar: Image("Avatar")) + .unredacted() + } + } + + @ViewBuilder + private func getWidgetBody(uiImage: Image, uiAvatar: Image) -> some View { + VStack { + Spacer() + HStack { + uiAvatar + .resizable() + .clipShape(Circle()) + .aspectRatio(contentMode: .fit) + .frame(width: 44, height: 44) + .overlay( + Circle() + .stroke(Color.white, lineWidth: 1) + .frame(width: 44, height: 44) + ) + .shadow(radius: 4) - Text(entry.displayName ?? "") - Spacer() - } + Text(entry.displayName ?? "") + .fontWeight(.semibold) + .shadow(radius: 8) + Spacer() } .padding(.leading, 8) .padding(.bottom, 8) } + .background { + uiImage + .resizable() + .aspectRatio(contentMode: .fill) + .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) + } } } diff --git a/VernissageWidget/Views/MediumWidgetView.swift b/VernissageWidget/Views/MediumWidgetView.swift index 592a291..7e4a7f0 100644 --- a/VernissageWidget/Views/MediumWidgetView.swift +++ b/VernissageWidget/Views/MediumWidgetView.swift @@ -12,42 +12,44 @@ struct MediumWidgetView: View { var body: some View { if let uiImage = entry.image, let uiAvatar = entry.avatar { - VStack { - Spacer() - HStack { - Image(uiImage: uiAvatar) - .resizable() - .clipShape(Circle()) - .aspectRatio(contentMode: .fit) - .frame(width: 32, height: 32) - - Text(entry.displayName ?? "") - Spacer() - } - .padding(.leading, 8) - .padding(.bottom, 8) - } - .background { - Image(uiImage: uiImage) - .resizable() - .aspectRatio(contentMode: .fill) - .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) - } + self.getWidgetBody(uiImage: Image(uiImage: uiImage), uiAvatar: Image(uiImage: uiAvatar)) } else { - VStack { - Spacer() - HStack { - Circle() - .foregroundColor(Color(UIColor.placeholderText)) - .frame(width: 32, height: 32) + self.getWidgetBody(uiImage: Image("Placeholder"), uiAvatar: Image("Avatar")) + .unredacted() + } + } + + @ViewBuilder + private func getWidgetBody(uiImage: Image, uiAvatar: Image) -> some View { + VStack { + Spacer() + HStack { + uiAvatar + .resizable() + .clipShape(Circle()) + .aspectRatio(contentMode: .fit) + .frame(width: 32, height: 32) + .overlay( + Circle() + .stroke(Color.white, lineWidth: 1) + .frame(width: 32, height: 32) + ) + .shadow(radius: 4) - Text(entry.displayName ?? "") - Spacer() - } + Text(entry.displayName ?? "") + .fontWeight(.semibold) + .shadow(radius: 8) + Spacer() } .padding(.leading, 8) .padding(.bottom, 8) } + .background { + uiImage + .resizable() + .aspectRatio(contentMode: .fill) + .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) + } } } diff --git a/VernissageWidget/Views/SmallWidgetView.swift b/VernissageWidget/Views/SmallWidgetView.swift index 9ad0743..913c5b9 100644 --- a/VernissageWidget/Views/SmallWidgetView.swift +++ b/VernissageWidget/Views/SmallWidgetView.swift @@ -12,27 +12,40 @@ struct SmallWidgetView: View { var body: some View { if let uiImage = entry.image, let uiAvatar = entry.avatar { - VStack { - Spacer() - HStack { - Image(uiImage: uiAvatar) - .resizable() - .clipShape(Circle()) - .aspectRatio(contentMode: .fit) - .frame(width: 22, height: 22) - Spacer() - } - .padding(.leading, 8) - .padding(.bottom, 8) - } - .background { - Image(uiImage: uiImage) - .resizable() - .aspectRatio(contentMode: .fill) - .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) - } + self.getWidgetBody(uiImage: Image(uiImage: uiImage), uiAvatar: Image(uiImage: uiAvatar)) } else { - EmptyView() + self.getWidgetBody(uiImage: Image("Placeholder"), uiAvatar: Image("Avatar")) + .unredacted() + } + } + + @ViewBuilder + private func getWidgetBody(uiImage: Image, uiAvatar: Image) -> some View { + VStack { + Spacer() + HStack { + uiAvatar + .resizable() + .clipShape(Circle()) + .aspectRatio(contentMode: .fit) + .frame(width: 22, height: 22) + .overlay( + Circle() + .stroke(Color.white, lineWidth: 1) + .frame(width: 22, height: 22) + ) + .shadow(radius: 4) + + Spacer() + } + .padding(.leading, 8) + .padding(.bottom, 8) + } + .background { + uiImage + .resizable() + .aspectRatio(contentMode: .fill) + .widgetURL(URL(string: "\(AppConstants.statusUri)/\(entry.statusId ?? "")")) } } }