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>"; };
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>"; };
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>"; };
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>"; };
@ -1105,7 +1106,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 56;
CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1142,7 +1143,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 56;
CURRENT_PROJECT_VERSION = 58;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@ -1271,13 +1272,14 @@
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */,
F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */,
F8B05AC929B488C600857221 /* Vernissage-003.xcdatamodel */,
F89F0605299139F6003DC875 /* Vernissage-002.xcdatamodel */,
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
);
currentVersion = F8B05ACC29B48DD000857221 /* Vernissage-004.xcdatamodel */;
currentVersion = F8CAE64129B8F1AF001E0372 /* Vernissage-005.xcdatamodel */;
path = Vernissage.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;

View File

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

View File

@ -98,4 +98,10 @@ class ApplicationSettingsHandler {
defaultSettings.showSensitive = value
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.
@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?) {
self.account = accountModel
self.lastSeenStatusId = lastSeenStatusId

View File

@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Vernissage-004.xcdatamodel</string>
<string>Vernissage-005.xcdatamodel</string>
</dict>
</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)) {
self.applicationState.avatarShape = avatarShape
}
self.applicationState.showSensitive = defaultSettings.showSensitive
self.applicationState.showPhotoDescription = defaultSettings.showPhotoDescription
}
private func setImagePipelines() {

View File

@ -11,6 +11,7 @@ struct MediaSettingsView: View {
@Environment(\.colorScheme) var colorScheme
@State var showSensitive = true
@State var showPhotoDescription = true
var body: some View {
Section("Media settings") {
@ -20,10 +21,17 @@ struct MediaSettingsView: View {
self.applicationState.showSensitive = 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 {
let defaultSettings = ApplicationSettingsHandler.shared.getDefaultSettings()
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 exifCreatedDate: String?
@State private var exifLens: String?
@State private var description: String?
@State var image: Image?
@ -61,7 +62,8 @@ struct StatusView: View {
exifCamera: $exifCamera,
exifExposure: $exifExposure,
exifCreatedDate: $exifCreatedDate,
exifLens: $exifLens)
exifLens: $exifLens,
description: $description)
.onTapGesture {
withoutAnimation {
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: "timelapse", value: self.exifExposure)
LabelIcon(iconName: "calendar", value: self.exifCreatedDate?.toDate(.isoDateTimeSec)?.formatted())
if self.applicationState.showPhotoDescription {
LabelIcon(iconName: "eye.trianglebadge.exclamationmark", value: self.description)
}
}
.padding(.bottom, 2)
.foregroundColor(.lightGrayColor)

View File

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