Files
Outpost/Outpost/Features/Collections/CollectionRowView.swift
T
Puranjay Savar Mattas 2c2f86f79b feat(collections): map Outline's named icon set to SF Symbols
Collection.icon can be a literal emoji or a string key into Outline's
own icon library (~50 custom outline-icons keys + ~90 FontAwesome
keys, per shared/utils/IconLibrary.tsx in outline/outline — a
different mapping than the outline-icons package itself, which is
keyed by PascalCase component name, not the string stored on the
collection). Only emoji was handled before, so most non-emoji
collections fell back to a generic folder glyph.

Covers the high-confidence subset with an unambiguous SF Symbol
match; unmapped keys keep falling back to the folder rather than
risk an invalid symbol name rendering blank.
2026-08-14 01:42:48 +01:00

45 lines
1.6 KiB
Swift

import SwiftUI
import OutlineKit
struct CollectionRowView: View {
let collection: OutlineCollection
var body: some View {
Label {
Text(collection.name)
} icon: {
if let emoji = collection.emojiIcon {
Text(emoji)
} else if let symbolName = collection.icon.flatMap(OutlineIconMapping.sfSymbolName) {
Image(systemName: symbolName)
.foregroundStyle(tintColor)
} else {
Image(systemName: "folder.fill")
.foregroundStyle(tintColor)
}
}
}
private var tintColor: Color {
collection.color.flatMap { Color(hex: $0) } ?? .accentColor
}
}
private extension OutlineCollection {
/// Outline's `icon` field holds either a literal emoji, or a string key
/// into Outline's own icon set (see OutlineIconMapping) — only the former
/// is renderable directly, the latter needs the lookup table.
var emojiIcon: String? {
// `isEmojiPresentation` misses symbol-class emoji that default to text
// presentation (e.g. some picked without a variation selector) — `isEmoji`
// is the broader, correct check for "this scalar can be an emoji at all".
// Plain ASCII digits/`#`/`*` also report `isEmoji == true` (they're valid
// keycap-sequence bases), so exclude the ASCII range to avoid treating a
// literal digit or punctuation icon name as an emoji.
guard let icon, icon.unicodeScalars.contains(where: { $0.properties.isEmoji && $0.value > 0x7F }) else {
return nil
}
return icon
}
}