Show photo descriptions.

This commit is contained in:
Marcin Czachursk 2023-03-08 17:43:05 +01:00
parent 5fce8a05e6
commit 1e482169ac
10 changed files with 131 additions and 6 deletions

View File

@ -317,6 +317,7 @@
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-001.xcdatamodel"; sourceTree = "<group>"; }; F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-001.xcdatamodel"; sourceTree = "<group>"; };
F8CAE63D29B8902D001E0372 /* ClearButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearButton.swift; sourceTree = "<group>"; }; F8CAE63D29B8902D001E0372 /* ClearButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearButton.swift; sourceTree = "<group>"; };
F8CAE63F29B8E6E1001E0372 /* UIApplication+Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Window.swift"; sourceTree = "<group>"; }; F8CAE63F29B8E6E1001E0372 /* UIApplication+Window.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Window.swift"; sourceTree = "<group>"; };
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-005.xcdatamodel"; sourceTree = "<group>"; };
F8CC95CD2970761D00C9C2AC /* TintColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TintColor.swift; sourceTree = "<group>"; }; F8CC95CD2970761D00C9C2AC /* TintColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TintColor.swift; sourceTree = "<group>"; };
F8CEEDF729ABADDD00DBED66 /* UIImage+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Size.swift"; sourceTree = "<group>"; }; F8CEEDF729ABADDD00DBED66 /* UIImage+Size.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Size.swift"; sourceTree = "<group>"; };
F8CEEDF929ABAFD200DBED66 /* ImageFileTranseferable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageFileTranseferable.swift; sourceTree = "<group>"; }; F8CEEDF929ABAFD200DBED66 /* ImageFileTranseferable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageFileTranseferable.swift; sourceTree = "<group>"; };
@ -1105,7 +1106,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 56; CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8; DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -1142,7 +1143,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 56; CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8; DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES; ENABLE_PREVIEWS = YES;
@ -1271,13 +1272,14 @@
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = { F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
isa = XCVersionGroup; isa = XCVersionGroup;
children = ( children = (
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */,
F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */, F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */,
F8B05AC929B488C600857221 /* Vernissage-003.xcdatamodel */, F8B05AC929B488C600857221 /* Vernissage-003.xcdatamodel */,
F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */, F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */,
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */, F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */, F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
); );
currentVersion = F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */; currentVersion = F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */;
path = Vernissage.xcdatamodeld; path = Vernissage.xcdatamodeld;
sourceTree = "<group>"; sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel; versionGroupType = wrapper.xcdatamodel;

View File

@ -26,6 +26,7 @@ extension ApplicationSettings {
@NSManaged public var hapticNotificationEnabled: Bool @NSManaged public var hapticNotificationEnabled: Bool
@NSManaged public var showSensitive: Bool @NSManaged public var showSensitive: Bool
@NSManaged public var showPhotoDescription: Bool
} }
extension ApplicationSettings : Identifiable { extension ApplicationSettings : Identifiable {

View File

@ -98,4 +98,10 @@ class ApplicationSettingsHandler {
defaultSettings.showSensitive = value defaultSettings.showSensitive = value
CoreDataHandler.shared.save() CoreDataHandler.shared.save()
} }
func setShowPhotoDescription(value: Bool) {
let defaultSettings = self.getDefaultSettings()
defaultSettings.showPhotoDescription = value
CoreDataHandler.shared.save()
}
} }

View File

@ -73,6 +73,9 @@ public class ApplicationState: ObservableObject {
/// Should sensitive photos without mask. /// Should sensitive photos without mask.
@Published var showSensitive = false @Published var showSensitive = false
/// Should photo description for visually impaired be displayed.
@Published var showPhotoDescription = false
public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?) { public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?) {
self.account = accountModel self.account = accountModel
self.lastSeenStatusId = lastSeenStatusId self.lastSeenStatusId = lastSeenStatusId

View File

@ -3,6 +3,6 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>_XCCurrentVersionName</key> <key>_XCCurrentVersionName</key>
<string>Vernissage-004.xcdatamodel</string> <string>Vernissage-005.xcdatamodel</string>
</dict> </dict>
</plist> </plist>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22C65" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="AccountData" representedClassName="AccountData" syncable="YES">
<attribute name="accessToken" optional="YES" attributeType="String"/>
<attribute name="acct" attributeType="String"/>
<attribute name="avatar" optional="YES" attributeType="URI"/>
<attribute name="avatarData" optional="YES" attributeType="Binary"/>
<attribute name="clientId" attributeType="String"/>
<attribute name="clientSecret" attributeType="String"/>
<attribute name="clientVapidKey" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="displayName" optional="YES" attributeType="String"/>
<attribute name="followersCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="followingCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="header" optional="YES" attributeType="URI"/>
<attribute name="id" attributeType="String"/>
<attribute name="lastSeenStatusId" optional="YES" attributeType="String"/>
<attribute name="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="note" optional="YES" attributeType="String"/>
<attribute name="refreshToken" optional="YES" attributeType="String"/>
<attribute name="serverUrl" attributeType="URI"/>
<attribute name="statusesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="username" attributeType="String"/>
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="StatusData" inverseName="pixelfedAccount" inverseEntity="StatusData"/>
</entity>
<entity name="ApplicationSettings" representedClassName="ApplicationSettings" syncable="YES">
<attribute name="avatarShape" attributeType="Integer 32" defaultValueString="1" usesScalarValueType="YES"/>
<attribute name="currentAccount" optional="YES" attributeType="String"/>
<attribute name="hapticAnimationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticButtonPressEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticNotificationEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticRefreshEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="hapticTabSelectionEnabled" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
<attribute name="lastRefreshTokens" attributeType="Date" defaultDateTimeInterval="694256400" usesScalarValueType="NO"/>
<attribute name="showPhotoDescription" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="showSensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="theme" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="tintColor" attributeType="Integer 32" defaultValueString="2" usesScalarValueType="YES"/>
</entity>
<entity name="AttachmentData" representedClassName="AttachmentData" syncable="YES">
<attribute name="blurhash" optional="YES" attributeType="String"/>
<attribute name="data" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES"/>
<attribute name="exifCamera" optional="YES" attributeType="String"/>
<attribute name="exifCreatedDate" optional="YES" attributeType="String"/>
<attribute name="exifExposure" optional="YES" attributeType="String"/>
<attribute name="exifLens" optional="YES" attributeType="String"/>
<attribute name="id" attributeType="String"/>
<attribute name="metaImageHeight" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="metaImageWidth" optional="YES" attributeType="Integer 32" defaultValueString="0.0" usesScalarValueType="YES"/>
<attribute name="previewUrl" optional="YES" attributeType="URI"/>
<attribute name="remoteUrl" optional="YES" attributeType="URI"/>
<attribute name="statusId" attributeType="String"/>
<attribute name="text" optional="YES" attributeType="String"/>
<attribute name="type" attributeType="String"/>
<attribute name="url" attributeType="URI"/>
<relationship name="statusRelation" maxCount="1" deletionRule="Nullify" destinationEntity="StatusData" inverseName="attachmentsRelation" inverseEntity="StatusData"/>
</entity>
<entity name="StatusData" representedClassName="StatusData" syncable="YES">
<attribute name="accountAvatar" optional="YES" attributeType="URI"/>
<attribute name="accountDisplayName" optional="YES" attributeType="String"/>
<attribute name="accountId" attributeType="String"/>
<attribute name="accountUsername" optional="YES" attributeType="String"/>
<attribute name="applicationName" optional="YES" attributeType="String"/>
<attribute name="applicationWebsite" optional="YES" attributeType="URI"/>
<attribute name="bookmarked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="content" attributeType="String"/>
<attribute name="createdAt" attributeType="String"/>
<attribute name="favourited" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="favouritesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="id" attributeType="String"/>
<attribute name="inReplyToAccount" optional="YES" attributeType="String"/>
<attribute name="inReplyToId" optional="YES" attributeType="String"/>
<attribute name="muted" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="pinned" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="reblogged" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="rebloggedAccountAvatar" optional="YES" attributeType="URI"/>
<attribute name="rebloggedAccountDisplayName" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountId" optional="YES" attributeType="String"/>
<attribute name="rebloggedAccountUsername" optional="YES" attributeType="String"/>
<attribute name="rebloggedStatusId" optional="YES" attributeType="String"/>
<attribute name="reblogsCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="repliesCount" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
<attribute name="sensitive" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
<attribute name="spoilerText" optional="YES" attributeType="String"/>
<attribute name="uri" attributeType="String"/>
<attribute name="url" optional="YES" attributeType="URI"/>
<attribute name="visibility" attributeType="String"/>
<relationship name="attachmentsRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
<relationship name="pixelfedAccount" maxCount="1" deletionRule="Nullify" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
</entity>
</model>

View File

@ -146,6 +146,9 @@ struct VernissageApp: App {
if let avatarShape = AvatarShape(rawValue: Int(defaultSettings.avatarShape)) { if let avatarShape = AvatarShape(rawValue: Int(defaultSettings.avatarShape)) {
self.applicationState.avatarShape = avatarShape self.applicationState.avatarShape = avatarShape
} }
self.applicationState.showSensitive = defaultSettings.showSensitive
self.applicationState.showPhotoDescription = defaultSettings.showPhotoDescription
} }
private func setImagePipelines() { private func setImagePipelines() {

View File

@ -11,6 +11,7 @@ struct MediaSettingsView: View {
@Environment(\.colorScheme) var colorScheme @Environment(\.colorScheme) var colorScheme
@State var showSensitive = true @State var showSensitive = true
@State var showPhotoDescription = true
var body: some View { var body: some View {
Section("Media settings") { Section("Media settings") {
@ -20,10 +21,17 @@ struct MediaSettingsView: View {
self.applicationState.showSensitive = newValue self.applicationState.showSensitive = newValue
ApplicationSettingsHandler.shared.setShowSensitive(value: newValue) ApplicationSettingsHandler.shared.setShowSensitive(value: newValue)
} }
Toggle("Show photo description", isOn: $showPhotoDescription)
.onChange(of: showPhotoDescription) { newValue in
self.applicationState.showPhotoDescription = newValue
ApplicationSettingsHandler.shared.setShowPhotoDescription(value: newValue)
}
} }
.onAppear { .onAppear {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings() let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
self.showSensitive = defaultSettings.showSensitive self.showSensitive = defaultSettings.showSensitive
self.showPhotoDescription = defaultSettings.showPhotoDescription
} }
} }
} }

View File

@ -31,6 +31,7 @@ struct StatusView: View {
@State private var exifExposure: String? @State private var exifExposure: String?
@State private var exifCreatedDate: String? @State private var exifCreatedDate: String?
@State private var exifLens: String? @State private var exifLens: String?
@State private var description: String?
@State var image: Image? @State var image: Image?
@ -61,7 +62,8 @@ struct StatusView: View {
exifCamera: $exifCamera, exifCamera: $exifCamera,
exifExposure: $exifExposure, exifExposure: $exifExposure,
exifCreatedDate: $exifCreatedDate, exifCreatedDate: $exifCreatedDate,
exifLens: $exifLens) exifLens: $exifLens,
description: $description)
.onTapGesture { .onTapGesture {
withoutAnimation { withoutAnimation {
if let attachment = self.statusViewModel?.mediaAttachments.first(where: { $0.id == self.selectedAttachmentId }), if let attachment = self.statusViewModel?.mediaAttachments.first(where: { $0.id == self.selectedAttachmentId }),
@ -100,6 +102,10 @@ struct StatusView: View {
LabelIcon(iconName: "camera.aperture", value: self.exifLens) LabelIcon(iconName: "camera.aperture", value: self.exifLens)
LabelIcon(iconName: "timelapse", value: self.exifExposure) LabelIcon(iconName: "timelapse", value: self.exifExposure)
LabelIcon(iconName: "calendar", value: self.exifCreatedDate?.toDate(.isoDateTimeSec)?.formatted()) LabelIcon(iconName: "calendar", value: self.exifCreatedDate?.toDate(.isoDateTimeSec)?.formatted())
if self.applicationState.showPhotoDescription {
LabelIcon(iconName: "eye.trianglebadge.exclamationmark", value: self.description)
}
} }
.padding(.bottom, 2) .padding(.bottom, 2)
.foregroundColor(.lightGrayColor) .foregroundColor(.lightGrayColor)

View File

@ -19,19 +19,22 @@ struct ImagesCarousel: View {
@Binding public var exifExposure: String? @Binding public var exifExposure: String?
@Binding public var exifCreatedDate: String? @Binding public var exifCreatedDate: String?
@Binding public var exifLens: String? @Binding public var exifLens: String?
@Binding public var description: String?
init(attachments: [AttachmentModel], init(attachments: [AttachmentModel],
selectedAttachmentId: Binding<String?>, selectedAttachmentId: Binding<String?>,
exifCamera: Binding<String?>, exifCamera: Binding<String?>,
exifExposure: Binding<String?>, exifExposure: Binding<String?>,
exifCreatedDate: Binding<String?>, exifCreatedDate: Binding<String?>,
exifLens: Binding<String?> exifLens: Binding<String?>,
description: Binding<String?>
) { ) {
_selectedAttachmentId = selectedAttachmentId _selectedAttachmentId = selectedAttachmentId
_exifCamera = exifCamera _exifCamera = exifCamera
_exifExposure = exifExposure _exifExposure = exifExposure
_exifCreatedDate = exifCreatedDate _exifCreatedDate = exifCreatedDate
_exifLens = exifLens _exifLens = exifLens
_description = description
self.attachments = attachments self.attachments = attachments
self.selected = String.empty() self.selected = String.empty()
@ -85,6 +88,7 @@ struct ImagesCarousel: View {
self.exifExposure = attachment.exifExposure self.exifExposure = attachment.exifExposure
self.exifCreatedDate = attachment.exifCreatedDate self.exifCreatedDate = attachment.exifCreatedDate
self.exifLens = attachment.exifLens self.exifLens = attachment.exifLens
self.description = attachment.description
} }
}) })
.onAppear { .onAppear {