Add rounded rectangle avatars.
This commit is contained in:
parent
a4970f9fcd
commit
50a4c98d8b
|
@ -45,6 +45,8 @@
|
|||
F85DBF93296760790069BF89 /* CacheAvatarService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85DBF92296760790069BF89 /* CacheAvatarService.swift */; };
|
||||
F85E1320297409CD006A051D /* ErrorsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F85E131F297409CD006A051D /* ErrorsService.swift */; };
|
||||
F85E132529741F05006A051D /* ActivityIndicatorView in Frameworks */ = {isa = PBXBuildFile; productRef = F85E132429741F05006A051D /* ActivityIndicatorView */; };
|
||||
F86167C6297FE6CC004D1F67 /* AvatarShapesSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86167C5297FE6CC004D1F67 /* AvatarShapesSection.swift */; };
|
||||
F86167C8297FE781004D1F67 /* AvatarShape.swift in Sources */ = {isa = PBXBuildFile; fileRef = F86167C7297FE781004D1F67 /* AvatarShape.swift */; };
|
||||
F866F6A0296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */; };
|
||||
F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */; };
|
||||
F866F6A329604161002E8F88 /* AccountDataHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F866F6A229604161002E8F88 /* AccountDataHandler.swift */; };
|
||||
|
@ -77,7 +79,7 @@
|
|||
F88E4D50297EA5230057491A /* HTML2Markdown in Frameworks */ = {isa = PBXBuildFile; productRef = F88E4D4F297EA5230057491A /* HTML2Markdown */; };
|
||||
F88E4D52297EA6DA0057491A /* String+Markdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D51297EA6DA0057491A /* String+Markdown.swift */; };
|
||||
F88E4D54297EA7EE0057491A /* MarkdownFormattedText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D53297EA7EE0057491A /* MarkdownFormattedText.swift */; };
|
||||
F88E4D56297EAD6E0057491A /* View+Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D55297EAD6E0057491A /* View+Router.swift */; };
|
||||
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D55297EAD6E0057491A /* AppRouteur.swift */; };
|
||||
F88E4D5A297ECEE60057491A /* SearchService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88E4D59297ECEE60057491A /* SearchService.swift */; };
|
||||
F88FAD21295F3944009B20C9 /* HomeFeedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD20295F3944009B20C9 /* HomeFeedView.swift */; };
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F88FAD26295F400E009B20C9 /* NotificationsView.swift */; };
|
||||
|
@ -148,6 +150,9 @@
|
|||
F85DBF8E296732E20069BF89 /* AccountsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsView.swift; sourceTree = "<group>"; };
|
||||
F85DBF92296760790069BF89 /* CacheAvatarService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheAvatarService.swift; sourceTree = "<group>"; };
|
||||
F85E131F297409CD006A051D /* ErrorsService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorsService.swift; sourceTree = "<group>"; };
|
||||
F86167C5297FE6CC004D1F67 /* AvatarShapesSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarShapesSection.swift; sourceTree = "<group>"; };
|
||||
F86167C7297FE781004D1F67 /* AvatarShape.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarShape.swift; sourceTree = "<group>"; };
|
||||
F86167C9297FF423004D1F67 /* Vernissage20230121-001.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage20230121-001.xcdatamodel"; sourceTree = "<group>"; };
|
||||
F866F69E296040A8002E8F88 /* ApplicationSettings+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApplicationSettings+CoreDataClass.swift"; sourceTree = "<group>"; };
|
||||
F866F69F296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ApplicationSettings+CoreDataProperties.swift"; sourceTree = "<group>"; };
|
||||
F866F6A229604161002E8F88 /* AccountDataHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDataHandler.swift; sourceTree = "<group>"; };
|
||||
|
@ -182,7 +187,7 @@
|
|||
F88E4D49297EA0490057491A /* RouterPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RouterPath.swift; sourceTree = "<group>"; };
|
||||
F88E4D51297EA6DA0057491A /* String+Markdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Markdown.swift"; sourceTree = "<group>"; };
|
||||
F88E4D53297EA7EE0057491A /* MarkdownFormattedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownFormattedText.swift; sourceTree = "<group>"; };
|
||||
F88E4D55297EAD6E0057491A /* View+Router.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Router.swift"; sourceTree = "<group>"; };
|
||||
F88E4D55297EAD6E0057491A /* AppRouteur.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppRouteur.swift; sourceTree = "<group>"; };
|
||||
F88E4D59297ECEE60057491A /* SearchService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchService.swift; sourceTree = "<group>"; };
|
||||
F88FAD20295F3944009B20C9 /* HomeFeedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeFeedView.swift; sourceTree = "<group>"; };
|
||||
F88FAD26295F400E009B20C9 /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
|
@ -294,7 +299,6 @@
|
|||
F8984E4C296B648000A2610F /* UIImage+Blurhash.swift */,
|
||||
F8996DEA2971D29D0043EEC6 /* View+Transition.swift */,
|
||||
F88E4D43297E82EB0057491A /* Status+MediaAttachmentType.swift */,
|
||||
F88E4D55297EAD6E0057491A /* View+Router.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
@ -306,6 +310,7 @@
|
|||
F866F6AD29606367002E8F88 /* ApplicationViewMode.swift */,
|
||||
F8CC95CD2970761D00C9C2AC /* TintColor.swift */,
|
||||
F89D6C3E29716E41001DA3D4 /* Theme.swift */,
|
||||
F86167C7297FE781004D1F67 /* AvatarShape.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
@ -412,6 +417,7 @@
|
|||
F8341F94295C63FE009C8EE6 /* Extensions */,
|
||||
F8341F93295C63E2009C8EE6 /* Views */,
|
||||
F88C246B295C37B80006098B /* VernissageApp.swift */,
|
||||
F88E4D55297EAD6E0057491A /* AppRouteur.swift */,
|
||||
F866F6A929605AFA002E8F88 /* SceneDelegate.swift */,
|
||||
F88C246F295C37BB0006098B /* Assets.xcassets */,
|
||||
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */,
|
||||
|
@ -480,6 +486,7 @@
|
|||
F89D6C4129717FDC001DA3D4 /* AccountsSection.swift */,
|
||||
F89D6C4329718092001DA3D4 /* AccentsSection.swift */,
|
||||
F89D6C4529718193001DA3D4 /* ThemeSection.swift */,
|
||||
F86167C5297FE6CC004D1F67 /* AvatarShapesSection.swift */,
|
||||
);
|
||||
path = SettingsView;
|
||||
sourceTree = "<group>";
|
||||
|
@ -661,13 +668,14 @@
|
|||
F86B7214296BFDCE00EE59EC /* UserProfileHeader.swift in Sources */,
|
||||
F88E4D46297E89DF0057491A /* TrendsService.swift in Sources */,
|
||||
F85D497D29640D5900751DF7 /* InteractionRow.swift in Sources */,
|
||||
F86167C6297FE6CC004D1F67 /* AvatarShapesSection.swift in Sources */,
|
||||
F866F6A729604629002E8F88 /* SignInView.swift in Sources */,
|
||||
F8C14392296AF0B3001FE31D /* String+Exif.swift in Sources */,
|
||||
F85E1320297409CD006A051D /* ErrorsService.swift in Sources */,
|
||||
F88C246C295C37B80006098B /* VernissageApp.swift in Sources */,
|
||||
F802884F297AEED5000BDD51 /* DatabaseError.swift in Sources */,
|
||||
F85D4971296402DC00751DF7 /* AuthorizationService.swift in Sources */,
|
||||
F88E4D56297EAD6E0057491A /* View+Router.swift in Sources */,
|
||||
F88E4D56297EAD6E0057491A /* AppRouteur.swift in Sources */,
|
||||
F88FAD32295F5029009B20C9 /* RemoteFileService.swift in Sources */,
|
||||
F88FAD27295F400E009B20C9 /* NotificationsView.swift in Sources */,
|
||||
F86B7216296BFFDA00EE59EC /* UserProfileStatuses.swift in Sources */,
|
||||
|
@ -681,6 +689,7 @@
|
|||
F866F6AE29606367002E8F88 /* ApplicationViewMode.swift in Sources */,
|
||||
F8A93D802965FED4001D8331 /* AccountService.swift in Sources */,
|
||||
F866F6AA29605AFA002E8F88 /* SceneDelegate.swift in Sources */,
|
||||
F86167C8297FE781004D1F67 /* AvatarShape.swift in Sources */,
|
||||
F85D4973296406E700751DF7 /* BottomRight.swift in Sources */,
|
||||
F898DE702972868A004B4A6A /* String+Empty.swift in Sources */,
|
||||
F86B7218296C27C100EE59EC /* ActionButton.swift in Sources */,
|
||||
|
@ -984,11 +993,12 @@
|
|||
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
F86167C9297FF423004D1F67 /* Vernissage20230121-001.xcdatamodel */,
|
||||
F89D6C3B29716DBC001DA3D4 /* Vernissage20230113-001.xcdatamodel */,
|
||||
F8AF2A61297073FE00D2DA3F /* Vernissage20230112-001.xcdatamodel */,
|
||||
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
|
||||
);
|
||||
currentVersion = F89D6C3B29716DBC001DA3D4 /* Vernissage20230113-001.xcdatamodel */;
|
||||
currentVersion = F86167C9297FF423004D1F67 /* Vernissage20230121-001.xcdatamodel */;
|
||||
path = Vernissage.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
versionGroupType = wrapper.xcdatamodel;
|
||||
|
|
|
@ -16,6 +16,7 @@ extension ApplicationSettings {
|
|||
@NSManaged public var currentAccount: String?
|
||||
@NSManaged public var theme: Int32
|
||||
@NSManaged public var tintColor: Int32
|
||||
@NSManaged public var avatarShape: Int32
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,12 @@ class ApplicationSettingsHandler {
|
|||
CoreDataHandler.shared.save()
|
||||
}
|
||||
|
||||
func setDefaultAvatarShape(avatarShape: AvatarShape) {
|
||||
let defaultSettings = self.getDefaultSettings()
|
||||
defaultSettings.avatarShape = Int32(avatarShape.rawValue)
|
||||
CoreDataHandler.shared.save()
|
||||
}
|
||||
|
||||
private func createApplicationSettingsEntity() -> ApplicationSettings {
|
||||
let context = CoreDataHandler.shared.container.viewContext
|
||||
return ApplicationSettings(context: context)
|
||||
|
|
|
@ -15,15 +15,6 @@ public class ApplicationState: ObservableObject {
|
|||
@Published var accountData: AccountData?
|
||||
@Published var tintColor = TintColor.accentColor2
|
||||
@Published var theme = Theme.system
|
||||
@Published var avatarShape = AvatarShape.circle
|
||||
@Published var showInteractionStatusId = String.empty()
|
||||
}
|
||||
|
||||
extension ApplicationState {
|
||||
public static var preview: ApplicationState = {
|
||||
let applicationState = ApplicationState()
|
||||
|
||||
applicationState.accountData = AccountData()
|
||||
|
||||
return applicationState
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
public enum AvatarShape: Int {
|
||||
case circle = 1
|
||||
case roundedRectangle = 2
|
||||
|
||||
func shape() -> some Shape {
|
||||
switch self {
|
||||
case .circle:
|
||||
return AnyShape(Circle())
|
||||
case .roundedRectangle:
|
||||
return AnyShape(RoundedRectangle(cornerRadius: 5))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,8 +7,16 @@
|
|||
import SwiftUI
|
||||
|
||||
public enum TintColor: Int {
|
||||
case accentColor1, accentColor2, accentColor3, accentColor4, accentColor5,
|
||||
accentColor6, accentColor7, accentColor8, accentColor9, accentColor10
|
||||
case accentColor1 = 1
|
||||
case accentColor2 = 2
|
||||
case accentColor3 = 3
|
||||
case accentColor4 = 4
|
||||
case accentColor5 = 5
|
||||
case accentColor6 = 6
|
||||
case accentColor7 = 7
|
||||
case accentColor8 = 8
|
||||
case accentColor9 = 9
|
||||
case accentColor10 = 10
|
||||
|
||||
public func color() -> Color {
|
||||
switch self {
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>_XCCurrentVersionName</key>
|
||||
<string>Vernissage20230113-001.xcdatamodel</string>
|
||||
<string>Vernissage20230121-001.xcdatamodel</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
<?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="locked" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="note" 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="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" 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="Cascade" destinationEntity="StatusData" inverseName="attachmentRelation" 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="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="attachmentRelation" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="AttachmentData" inverseName="statusRelation" inverseEntity="AttachmentData"/>
|
||||
<relationship name="pixelfedAccount" maxCount="1" deletionRule="No Action" destinationEntity="AccountData" inverseName="statuses" inverseEntity="AccountData"/>
|
||||
</entity>
|
||||
</model>
|
|
@ -59,6 +59,10 @@ struct VernissageApp: App {
|
|||
self.applicationState.theme = theme
|
||||
self.theme = theme.colorScheme()
|
||||
}
|
||||
|
||||
if let avatarShape = AvatarShape(rawValue: Int(defaultSettings.avatarShape)) {
|
||||
self.applicationState.avatarShape = avatarShape
|
||||
}
|
||||
|
||||
await AuthorizationService.shared.verifyAccount({ accountData in
|
||||
guard let accountData = accountData else {
|
||||
|
|
|
@ -173,13 +173,19 @@ struct MainView: View {
|
|||
if let avatarData = self.applicationState.accountData?.avatarData, let uiImage = UIImage(data: avatarData) {
|
||||
Image(uiImage: uiImage)
|
||||
.resizable()
|
||||
.clipShape(Circle())
|
||||
.clipShape(self.applicationState.avatarShape.shape())
|
||||
.frame(width: 32.0, height: 32.0)
|
||||
} else {
|
||||
Image(systemName: "person.circle")
|
||||
Image(systemName: "person")
|
||||
.resizable()
|
||||
.frame(width: 32.0, height: 32.0)
|
||||
.foregroundColor(.mainTextColor)
|
||||
.frame(width: 16, height: 16)
|
||||
.foregroundColor(.white)
|
||||
.padding(8)
|
||||
.background(Color.lightGrayColor)
|
||||
.clipShape(AvatarShape.circle.shape())
|
||||
.background(
|
||||
AvatarShape.circle.shape()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,6 @@ struct SettingsView: View {
|
|||
@State private var theme: ColorScheme?
|
||||
@State private var appVersion: String?
|
||||
@State private var appBundleVersion: String?
|
||||
|
||||
var onTintChange: ((TintColor) -> Void)?
|
||||
var onThemeChange: ((Theme) -> Void)?
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
|
@ -26,14 +23,13 @@ struct SettingsView: View {
|
|||
AccountsSection()
|
||||
|
||||
// Themes.
|
||||
ThemeSection { theme in
|
||||
changeTheme(theme: theme)
|
||||
}
|
||||
ThemeSection()
|
||||
|
||||
// Accents.
|
||||
AccentsSection { color in
|
||||
self.onTintChange?(color)
|
||||
}
|
||||
AccentsSection()
|
||||
|
||||
// Avatar shapes.
|
||||
AvatarShapesSection()
|
||||
|
||||
// Other.
|
||||
Section("Other") {
|
||||
|
@ -72,17 +68,12 @@ struct SettingsView: View {
|
|||
}
|
||||
.withAppRouteur()
|
||||
}
|
||||
.onChange(of: self.applicationState.theme) { newValue in
|
||||
// Change theme of current modal screen (unformtunatelly it's not changed autmatically.
|
||||
self.theme = self.applicationState.theme.colorScheme() ?? self.getSystemColorScheme()
|
||||
}
|
||||
}
|
||||
|
||||
private func changeTheme(theme: Theme) {
|
||||
// Change theme of current modal screen (unformtunatelly it's not changed autmatically_
|
||||
self.theme = theme.colorScheme() ?? self.getSystemColorScheme()
|
||||
|
||||
self.applicationState.theme = theme
|
||||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: theme)
|
||||
onThemeChange?(theme)
|
||||
}
|
||||
|
||||
|
||||
func getSystemColorScheme() -> ColorScheme {
|
||||
return UITraitCollection.current.userInterfaceStyle == .light ? .light : .dark
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import SwiftUI
|
|||
|
||||
struct AccentsSection: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
var onTintChange: ((TintColor) -> Void)?
|
||||
|
||||
private let accentColors1: [TintColor] = [.accentColor1, .accentColor2, .accentColor3, .accentColor4, .accentColor5]
|
||||
private let accentColors2: [TintColor] = [.accentColor6, .accentColor7, .accentColor8, .accentColor9, .accentColor10]
|
||||
|
@ -26,7 +24,6 @@ struct AccentsSection: View {
|
|||
.onTapGesture {
|
||||
self.applicationState.tintColor = color
|
||||
ApplicationSettingsHandler.shared.setDefaultTintColor(tintColor: color)
|
||||
self.onTintChange?(color)
|
||||
}
|
||||
if color == self.applicationState.tintColor {
|
||||
Image(systemName: "checkmark")
|
||||
|
@ -51,7 +48,6 @@ struct AccentsSection: View {
|
|||
.onTapGesture {
|
||||
self.applicationState.tintColor = color
|
||||
ApplicationSettingsHandler.shared.setDefaultTintColor(tintColor: color)
|
||||
self.onTintChange?(color)
|
||||
}
|
||||
if color == self.applicationState.tintColor {
|
||||
Image(systemName: "checkmark")
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// https://mczachurski.dev
|
||||
// Copyright © 2023 Marcin Czachurski and the repository contributors.
|
||||
// Licensed under the MIT License.
|
||||
//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AvatarShapesSection: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
var body: some View {
|
||||
Section("Avatar") {
|
||||
Button {
|
||||
self.applicationState.avatarShape = .circle
|
||||
ApplicationSettingsHandler.shared.setDefaultAvatarShape(avatarShape: .circle)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "person")
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.foregroundColor(.white)
|
||||
.padding(8)
|
||||
.background(Color.lightGrayColor)
|
||||
.clipShape(AvatarShape.circle.shape())
|
||||
.background(
|
||||
AvatarShape.circle.shape()
|
||||
)
|
||||
|
||||
Text("Circle")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
|
||||
if self.applicationState.avatarShape == .circle {
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
self.applicationState.avatarShape = .roundedRectangle
|
||||
ApplicationSettingsHandler.shared.setDefaultAvatarShape(avatarShape: .roundedRectangle)
|
||||
} label: {
|
||||
HStack {
|
||||
Image(systemName: "person")
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.foregroundColor(.white)
|
||||
.padding(8)
|
||||
.background(Color.lightGrayColor)
|
||||
.clipShape(AvatarShape.roundedRectangle.shape())
|
||||
.background(
|
||||
AvatarShape.roundedRectangle.shape()
|
||||
)
|
||||
Text("Rounded rectangle")
|
||||
.foregroundColor(.label)
|
||||
Spacer()
|
||||
|
||||
if self.applicationState.avatarShape == .roundedRectangle {
|
||||
Image(systemName: "checkmark")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,13 +9,12 @@ import SwiftUI
|
|||
struct ThemeSection: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
var onThemeChange: ((Theme) -> Void)?
|
||||
|
||||
var body: some View {
|
||||
Section("Theme") {
|
||||
Button {
|
||||
onThemeChange?(.system)
|
||||
self.applicationState.theme = .system
|
||||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .system)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("System")
|
||||
|
@ -28,7 +27,8 @@ struct ThemeSection: View {
|
|||
}
|
||||
|
||||
Button {
|
||||
onThemeChange?(.light)
|
||||
self.applicationState.theme = .light
|
||||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .light)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Light")
|
||||
|
@ -41,7 +41,8 @@ struct ThemeSection: View {
|
|||
}
|
||||
|
||||
Button {
|
||||
onThemeChange?(.dark)
|
||||
self.applicationState.theme = .dark
|
||||
ApplicationSettingsHandler.shared.setDefaultTheme(theme: .dark)
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Dark")
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
import SwiftUI
|
||||
|
||||
struct UserAvatar: View {
|
||||
@EnvironmentObject var applicationState: ApplicationState
|
||||
|
||||
@State public var accountId: String
|
||||
@State public var accountAvatar: URL?
|
||||
@State public var width = 48.0
|
||||
|
@ -16,7 +18,7 @@ struct UserAvatar: View {
|
|||
if let cachedAvatar = CacheAvatarService.shared.getImage(for: accountId) {
|
||||
cachedAvatar
|
||||
.resizable()
|
||||
.clipShape(Circle())
|
||||
.clipShape(applicationState.avatarShape.shape())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(width: self.width, height: self.height)
|
||||
}
|
||||
|
@ -25,23 +27,33 @@ struct UserAvatar: View {
|
|||
if let image = phase.image {
|
||||
image
|
||||
.resizable()
|
||||
.clipShape(Circle())
|
||||
.clipShape(applicationState.avatarShape.shape())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.onAppear {
|
||||
CacheAvatarService.shared.addImage(for: self.accountId, image: image)
|
||||
}
|
||||
} else if phase.error != nil {
|
||||
Image(systemName: "person.circle")
|
||||
Image(systemName: "person")
|
||||
.resizable()
|
||||
.clipShape(Circle())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.foregroundColor(.mainTextColor)
|
||||
.foregroundColor(.white)
|
||||
.padding(8)
|
||||
.background(Color.lightGrayColor)
|
||||
.clipShape(AvatarShape.circle.shape())
|
||||
.background(
|
||||
AvatarShape.circle.shape()
|
||||
)
|
||||
} else {
|
||||
Image(systemName: "person.circle")
|
||||
Image(systemName: "person")
|
||||
.resizable()
|
||||
.clipShape(Circle())
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.foregroundColor(.mainTextColor)
|
||||
.foregroundColor(.white)
|
||||
.padding(8)
|
||||
.background(Color.lightGrayColor)
|
||||
.clipShape(applicationState.avatarShape.shape())
|
||||
.background(
|
||||
AvatarShape.circle.shape()
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(width: self.width, height: self.height)
|
||||
|
@ -49,9 +61,3 @@ struct UserAvatar: View {
|
|||
}
|
||||
}
|
||||
|
||||
struct UserAvatar_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
UserAvatar(accountId: "")
|
||||
.previewLayout(.fixed(width: 128, height: 128))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue