diff --git a/Mlem.xcodeproj/project.pbxproj b/Mlem.xcodeproj/project.pbxproj index f07412ebf..25b1cacb4 100644 --- a/Mlem.xcodeproj/project.pbxproj +++ b/Mlem.xcodeproj/project.pbxproj @@ -421,6 +421,7 @@ CDB45C602AF1AF4900A1FF08 /* MentionModel+TrackerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB45C5F2AF1AF4900A1FF08 /* MentionModel+TrackerItem.swift */; }; CDB45C622AF1AF9B00A1FF08 /* ReplyModel+TrackerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB45C612AF1AF9B00A1FF08 /* ReplyModel+TrackerItem.swift */; }; CDB45C642AF1AFB900A1FF08 /* MessageModel+TrackerItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB45C632AF1AFB900A1FF08 /* MessageModel+TrackerItem.swift */; }; + CDB45C5A2AF0AEFE00A1FF08 /* AlternativeIconLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB45C592AF0AEFE00A1FF08 /* AlternativeIconLabel.swift */; }; CDC1C93C2A7AA76000072E3D /* InternetSpeed.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C93B2A7AA76000072E3D /* InternetSpeed.swift */; }; CDC1C93F2A7AB8C700072E3D /* AccessibilitySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C93E2A7AB8C700072E3D /* AccessibilitySettingsView.swift */; }; CDC1C9412A7ABA9C00072E3D /* ReadMarkStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC1C9402A7ABA9C00072E3D /* ReadMarkStyle.swift */; }; @@ -924,6 +925,7 @@ CDB45C5F2AF1AF4900A1FF08 /* MentionModel+TrackerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MentionModel+TrackerItem.swift"; sourceTree = ""; }; CDB45C612AF1AF9B00A1FF08 /* ReplyModel+TrackerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ReplyModel+TrackerItem.swift"; sourceTree = ""; }; CDB45C632AF1AFB900A1FF08 /* MessageModel+TrackerItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageModel+TrackerItem.swift"; sourceTree = ""; }; + CDB45C592AF0AEFE00A1FF08 /* AlternativeIconLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlternativeIconLabel.swift; sourceTree = ""; }; CDC1C93B2A7AA76000072E3D /* InternetSpeed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternetSpeed.swift; sourceTree = ""; }; CDC1C93E2A7AB8C700072E3D /* AccessibilitySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilitySettingsView.swift; sourceTree = ""; }; CDC1C9402A7ABA9C00072E3D /* ReadMarkStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkStyle.swift; sourceTree = ""; }; @@ -1102,6 +1104,7 @@ children = ( CD4E98A22A69BEDC0026C4D9 /* IconSettingsView.swift */, CD4E98A02A69BE980026C4D9 /* AlternativeIconCell.swift */, + CDB45C592AF0AEFE00A1FF08 /* AlternativeIconLabel.swift */, ); path = Icon; sourceTree = ""; @@ -3091,6 +3094,7 @@ 6D405B052A43E82300C65F9C /* Sidebar Header.swift in Sources */, CD4368B42AE23F3500BD8BD1 /* ChildTrackerProtocol.swift in Sources */, CD4368D92AE2478300BD8BD1 /* MentionModel+InboxItem.swift in Sources */, + CDB45C5A2AF0AEFE00A1FF08 /* AlternativeIconLabel.swift in Sources */, 50811B302A92049B006BA3F2 /* APICommunityView+Mock.swift in Sources */, CDA217F32A63202600BDA173 /* NSFW Overlay.swift in Sources */, CDB45C602AF1AF4900A1FF08 /* MentionModel+TrackerItem.swift in Sources */, diff --git a/Mlem/Assets.xcassets/AppIcon.appiconset/Contents.json b/Mlem/Assets.xcassets/AppIcon.appiconset/Contents.json index 2e5fb8d85..f4344003c 100644 --- a/Mlem/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Mlem/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "mlemmy-brighter.png", + "filename" : "logo.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/Mlem/Assets.xcassets/AppIcon.appiconset/logo.png b/Mlem/Assets.xcassets/AppIcon.appiconset/logo.png new file mode 100644 index 000000000..0d3bdb375 Binary files /dev/null and b/Mlem/Assets.xcassets/AppIcon.appiconset/logo.png differ diff --git a/Mlem/Assets.xcassets/Icons/Mlem by Clays.appiconset/Contents.json b/Mlem/Assets.xcassets/Icons/Mlem by Clays.appiconset/Contents.json new file mode 100644 index 000000000..2e5fb8d85 --- /dev/null +++ b/Mlem/Assets.xcassets/Icons/Mlem by Clays.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "mlemmy-brighter.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mlem/Assets.xcassets/AppIcon.appiconset/mlemmy-brighter.png b/Mlem/Assets.xcassets/Icons/Mlem by Clays.appiconset/mlemmy-brighter.png similarity index 100% rename from Mlem/Assets.xcassets/AppIcon.appiconset/mlemmy-brighter.png rename to Mlem/Assets.xcassets/Icons/Mlem by Clays.appiconset/mlemmy-brighter.png diff --git a/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/Contents.json b/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/Contents.json index d167619eb..f4344003c 100644 --- a/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/Contents.json +++ b/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "stargazer.png", + "filename" : "logo.png", "idiom" : "universal", "platform" : "ios", "size" : "1024x1024" diff --git a/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/logo.png b/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/logo.png new file mode 100644 index 000000000..0d3bdb375 Binary files /dev/null and b/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/logo.png differ diff --git a/Mlem/Assets.xcassets/Icons/Stargazer Dark By Sjmarf.appiconset/Contents.json b/Mlem/Assets.xcassets/Icons/Stargazer Dark By Sjmarf.appiconset/Contents.json new file mode 100644 index 000000000..d167619eb --- /dev/null +++ b/Mlem/Assets.xcassets/Icons/Stargazer Dark By Sjmarf.appiconset/Contents.json @@ -0,0 +1,14 @@ +{ + "images" : [ + { + "filename" : "stargazer.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/stargazer.png b/Mlem/Assets.xcassets/Icons/Stargazer Dark By Sjmarf.appiconset/stargazer.png similarity index 100% rename from Mlem/Assets.xcassets/Icons/Stargazer By Sjmarf.appiconset/stargazer.png rename to Mlem/Assets.xcassets/Icons/Stargazer Dark By Sjmarf.appiconset/stargazer.png diff --git a/Mlem/Assets.xcassets/logo.imageset/Contents.json b/Mlem/Assets.xcassets/logo.imageset/Contents.json index b14ca8654..7c58c478f 100644 --- a/Mlem/Assets.xcassets/logo.imageset/Contents.json +++ b/Mlem/Assets.xcassets/logo.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "mlem-reasonable.png", + "filename" : "logo.png", "idiom" : "universal" } ], diff --git a/Mlem/Assets.xcassets/logo.imageset/logo.png b/Mlem/Assets.xcassets/logo.imageset/logo.png new file mode 100644 index 000000000..0d3bdb375 Binary files /dev/null and b/Mlem/Assets.xcassets/logo.imageset/logo.png differ diff --git a/Mlem/Assets.xcassets/logo.imageset/mlem-reasonable.png b/Mlem/Assets.xcassets/logo.imageset/mlem-reasonable.png deleted file mode 100644 index 521efa9ad..000000000 Binary files a/Mlem/Assets.xcassets/logo.imageset/mlem-reasonable.png and /dev/null differ diff --git a/Mlem/Extensions/AlternativeIconCell.swift b/Mlem/Extensions/AlternativeIconCell.swift index a3f36b377..cafeacaf0 100644 --- a/Mlem/Extensions/AlternativeIconCell.swift +++ b/Mlem/Extensions/AlternativeIconCell.swift @@ -17,47 +17,9 @@ struct AlternativeIconCell: View { await setAppIcon(icon.id) } } label: { - HStack { - getImage() - .resizable() - .scaledToFit() - .frame(width: AppConstants.appIconSize, height: AppConstants.appIconSize) - .foregroundColor(Color.white) - .cornerRadius(AppConstants.appIconCornerRadius) - .overlay { - RoundedRectangle(cornerRadius: AppConstants.appIconCornerRadius) - .stroke(Color(.secondarySystemBackground), lineWidth: 1) - } - VStack(alignment: .leading) { - Text(icon.name) - if let author = icon.author { - Text(author) - .font(.footnote) - .foregroundColor(.secondary) - } - } - Spacer() - if icon.selected { - Image(systemName: Icons.success) - } - } + AlternativeIconLabel(icon: icon) }.accessibilityElement(children: .combine) } - - func getImage() -> Image { - let image = { - guard let id = icon.id else { - return Bundle.main.iconFileName - .flatMap { UIImage(named: $0) } - .map { - Image(uiImage: $0) - } ?? Image(systemName: Icons.noFile) - } - return Image(uiImage: UIImage(named: id) ?? UIImage(imageLiteralResourceName: id)) - } - - return image() - } } struct AlternativeIconCellPreview: PreviewProvider { diff --git a/Mlem/Extensions/IconSettingsView.swift b/Mlem/Extensions/IconSettingsView.swift index 5999cec01..4bf59f6d0 100644 --- a/Mlem/Extensions/IconSettingsView.swift +++ b/Mlem/Extensions/IconSettingsView.swift @@ -28,46 +28,63 @@ struct IconSettingsView: View { var body: some View { List { - ForEach(getAllIcons()) { icon in - AlternativeIconCell(icon: icon, setAppIcon: setAppIcon) - } + iconsList() } .fancyTabScrollCompatible() + .navigationTitle("App Icon") + } + + @ViewBuilder + func iconsList() -> some View { + let allIcons = getAllIcons() + let creators = allIcons.keys.sorted() + + ForEach(creators, id: \.self) { creator in + if let icons = allIcons[creator], !icons.isEmpty { + DisclosureGroup { + ForEach(icons) { icon in + AlternativeIconCell(icon: icon, setAppIcon: setAppIcon) + } + } label: { + AlternativeIconLabel(icon: AlternativeIcon(id: icons[0].id, name: creator, author: nil, selected: false)) + } + } + } } - func getAllIcons() -> [AlternativeIcon] { - guard let iconsBundle = Bundle.main.object(forInfoDictionaryKey: "CFBundleIcons") as? [String: Any?] - else { return [] } + func getAllIcons() -> [String: [AlternativeIcon]] { + guard let iconsBundle = Bundle.main.object(forInfoDictionaryKey: "CFBundleIcons") as? [String: Any?] else { return [:] } - guard let altIcons = iconsBundle["CFBundleAlternateIcons"] as? [String: Any?] - else { return [] } + guard let altIcons = iconsBundle["CFBundleAlternateIcons"] as? [String: Any?] else { return [:] } let currentIconSelection = UIApplication.shared.alternateIconName - - var allIcons = [ - AlternativeIcon(id: nil, name: "Mlem", author: "By Clay/s", selected: currentIconSelection == nil) - ] - allIcons.append(contentsOf: altIcons.keys.map { key in + + var ret: [String: [AlternativeIcon]] = .init() + + altIcons.keys.forEach { key in + // parse AlternativeIcon from icon data print("found icon: \(key)") let match = key.firstMatch(of: iconFinder) let name = (match?.output.1 != nil) ? String(match!.output.1) : key - var author = (match?.output.2 != nil) ? "By \(String(match!.output.2))" : "" + var author = (match?.output.2 != nil) ? "\(String(match!.output.2))" : "Anonymous" author = author.replacingOccurrences(of: "Clays", with: "Clay/s") - return AlternativeIcon(id: key, name: name, author: author, selected: currentIconSelection == key) - }.filter { - if let id = IconId(rawValue: $0.id ?? "Default"), - let requiredEasterFlag = easterDependentIcons[id] { - return easterTracker.flags.contains(requiredEasterFlag) + let icon = AlternativeIcon(id: key, name: name, author: author, selected: currentIconSelection == key) + + // if we should show this icon, add to map + if shouldShowIcon(icon: icon) { + ret[author, default: []].append(icon) } - return true - }.sorted(by: { lhs, rhs in - lhs.name < rhs.name - })) + } + + ret.keys.forEach { key in + ret[key] = ret[key]?.sorted { + $0.name < $1.name + } + } - return allIcons + return ret } - // static func getCurrentIcon() -> some View { static func getCurrentIcon() -> Image { let icon = AlternativeIcon( id: UIApplication.shared.alternateIconName, @@ -75,7 +92,7 @@ struct IconSettingsView: View { author: "", selected: false ) - return AlternativeIconCell(icon: icon) { _ in }.getImage() + return AlternativeIconLabel(icon: icon).getImage() } @MainActor @@ -87,6 +104,14 @@ struct IconSettingsView: View { // do nothing! } } + + private func shouldShowIcon(icon: AlternativeIcon) -> Bool { + if let id = IconId(rawValue: icon.id ?? "Default"), + let requiredEasterFlag = easterDependentIcons[id] { + return easterTracker.flags.contains(requiredEasterFlag) + } + return true + } } struct AlternativeIconsPreview: PreviewProvider { diff --git a/Mlem/Views/Tabs/Settings/Components/Views/Appearance/Icon/AlternativeIconLabel.swift b/Mlem/Views/Tabs/Settings/Components/Views/Appearance/Icon/AlternativeIconLabel.swift new file mode 100644 index 000000000..de2847479 --- /dev/null +++ b/Mlem/Views/Tabs/Settings/Components/Views/Appearance/Icon/AlternativeIconLabel.swift @@ -0,0 +1,54 @@ +// +// AlternativeIconCell.swift +// Mlem +// +// Created by tht7 on 28/06/2023. +// + +import SwiftUI + +struct AlternativeIconLabel: View { + let icon: AlternativeIcon + + var body: some View { + HStack { + getImage() + .resizable() + .scaledToFit() + .frame(width: AppConstants.appIconSize, height: AppConstants.appIconSize) + .foregroundColor(Color.white) + .cornerRadius(AppConstants.appIconCornerRadius) + .overlay { + RoundedRectangle(cornerRadius: AppConstants.appIconCornerRadius) + .stroke(Color(.secondarySystemBackground), lineWidth: 1) + } + VStack(alignment: .leading) { + Text(icon.name) + if let author = icon.author { + Text(author) + .font(.footnote) + .foregroundColor(.secondary) + } + } + Spacer() + if icon.selected { + Image(systemName: Icons.success) + } + } + } + + func getImage() -> Image { + let image = { + guard let id = icon.id else { + return Bundle.main.iconFileName + .flatMap { UIImage(named: $0) } + .map { + Image(uiImage: $0) + } ?? Image(systemName: Icons.noFile) + } + return Image(uiImage: UIImage(named: id) ?? UIImage(imageLiteralResourceName: id)) + } + + return image() + } +}